From f5ca3a6dbe3dfe1ba3dc8ba64672bc44a983014a Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Thu, 13 May 2021 14:05:47 -0700 Subject: [PATCH 01/53] Push Notifications Components --- ProjectReunion.sln | 82 ++++++ dev/AppLifecycle/AppInstance.cpp | 19 +- dev/AppLifecycle/AppLifecycle.idl | 2 +- .../ProjectReunion_DLL.vcxproj | 1 + .../GetRawNotificationEventArgs.h | 32 +++ .../PushNotificationActivationInfo.cpp | 41 +++ .../PushNotificationActivationInfo.h | 28 ++ .../PushNotificationBackgroundTask.cpp | 25 ++ .../PushNotificationBackgroundTask.h | 28 ++ .../PushNotificationChannel.cpp | 68 +++++ .../PushNotificationChannel.h | 28 ++ .../PushNotificationCreateChannelResult.cpp | 25 ++ .../PushNotificationCreateChannelResult.h | 26 ++ .../PushNotificationManager.cpp | 263 ++++++++++++++++++ .../PushNotificationManager.h | 24 ++ .../PushNotificationReceivedEventArgs.cpp | 118 ++++++++ .../PushNotificationReceivedEventArgs.h | 32 +++ .../PushNotificationRegistrationToken.cpp | 24 ++ .../PushNotificationRegistrationToken.h | 25 ++ dev/PushNotifications/PushNotifications.idl | 134 +++++++++ .../PushNotifications.vcxitems | 39 +++ dev/PushNotifications/externs.h | 7 + .../appxmanifest.xml | 6 + .../AppLifecycleTestPackage.wapproj | 3 +- .../Package.appxmanifest | 4 +- .../PushNotificationsDemoApp.vcxproj | 177 ++++++++++++ .../PushNotificationsDemoApp.vcxproj.filters | 33 +++ .../PushNotificationsDemoApp/main.cpp | 130 +++++++++ .../PushNotificationsDemoApp/packages.config | 5 + .../TestApps/PushNotificationsDemoApp/pch.cpp | 3 + test/TestApps/PushNotificationsDemoApp/pch.h | 19 ++ .../Images/LockScreenLogo.scale-200.png | Bin 0 -> 1430 bytes .../Images/SplashScreen.scale-200.png | Bin 0 -> 7700 bytes .../Images/Square150x150Logo.scale-200.png | Bin 0 -> 2937 bytes .../Images/Square44x44Logo.scale-200.png | Bin 0 -> 1647 bytes ...x44Logo.targetsize-24_altform-unplated.png | Bin 0 -> 1255 bytes .../Images/StoreLogo.png | Bin 0 -> 1451 bytes .../Images/Wide310x150Logo.scale-200.png | Bin 0 -> 3204 bytes .../Package.appxmanifest | 65 +++++ .../PushNotificationsDemoPackage.wapproj | 121 ++++++++ 40 files changed, 1629 insertions(+), 8 deletions(-) create mode 100644 dev/PushNotifications/GetRawNotificationEventArgs.h create mode 100644 dev/PushNotifications/PushNotificationActivationInfo.cpp create mode 100644 dev/PushNotifications/PushNotificationActivationInfo.h create mode 100644 dev/PushNotifications/PushNotificationBackgroundTask.cpp create mode 100644 dev/PushNotifications/PushNotificationBackgroundTask.h create mode 100644 dev/PushNotifications/PushNotificationChannel.cpp create mode 100644 dev/PushNotifications/PushNotificationChannel.h create mode 100644 dev/PushNotifications/PushNotificationCreateChannelResult.cpp create mode 100644 dev/PushNotifications/PushNotificationCreateChannelResult.h create mode 100644 dev/PushNotifications/PushNotificationManager.cpp create mode 100644 dev/PushNotifications/PushNotificationManager.h create mode 100644 dev/PushNotifications/PushNotificationReceivedEventArgs.cpp create mode 100644 dev/PushNotifications/PushNotificationReceivedEventArgs.h create mode 100644 dev/PushNotifications/PushNotificationRegistrationToken.cpp create mode 100644 dev/PushNotifications/PushNotificationRegistrationToken.h create mode 100644 dev/PushNotifications/PushNotifications.idl create mode 100644 dev/PushNotifications/PushNotifications.vcxitems create mode 100644 dev/PushNotifications/externs.h create mode 100644 test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj create mode 100644 test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj.filters create mode 100644 test/TestApps/PushNotificationsDemoApp/main.cpp create mode 100644 test/TestApps/PushNotificationsDemoApp/packages.config create mode 100644 test/TestApps/PushNotificationsDemoApp/pch.cpp create mode 100644 test/TestApps/PushNotificationsDemoApp/pch.h create mode 100644 test/TestApps/PushNotificationsDemoPackage/Images/LockScreenLogo.scale-200.png create mode 100644 test/TestApps/PushNotificationsDemoPackage/Images/SplashScreen.scale-200.png create mode 100644 test/TestApps/PushNotificationsDemoPackage/Images/Square150x150Logo.scale-200.png create mode 100644 test/TestApps/PushNotificationsDemoPackage/Images/Square44x44Logo.scale-200.png create mode 100644 test/TestApps/PushNotificationsDemoPackage/Images/Square44x44Logo.targetsize-24_altform-unplated.png create mode 100644 test/TestApps/PushNotificationsDemoPackage/Images/StoreLogo.png create mode 100644 test/TestApps/PushNotificationsDemoPackage/Images/Wide310x150Logo.scale-200.png create mode 100644 test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest create mode 100644 test/TestApps/PushNotificationsDemoPackage/PushNotificationsDemoPackage.wapproj diff --git a/ProjectReunion.sln b/ProjectReunion.sln index 0de2129c9a..c1632e21b7 100644 --- a/ProjectReunion.sln +++ b/ProjectReunion.sln @@ -120,8 +120,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ManualTestApp", "test\TestA EndProject Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "AppLifecycleTestPackage", "test\TestApps\AppLifecycleTestPackage\AppLifecycleTestPackage.wapproj", "{A3FBA80D-5B35-471F-9A45-DB4B29E195B9}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PushNotifications", "PushNotifications", "{91D03B95-1B0C-4BEB-8441-30DA7D615538}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PushNotifications", "dev\PushNotifications\PushNotifications.vcxitems", "{103C0C23-7BA8-4D44-A63C-83488E2E3A81}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PushNotificationsDemoApp", "test\TestApps\PushNotificationsDemoApp\PushNotificationsDemoApp.vcxproj", "{5B2D17FE-C371-417F-860C-3D32397C2404}" +EndProject +Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "PushNotificationsDemoPackage", "test\TestApps\PushNotificationsDemoPackage\PushNotificationsDemoPackage.wapproj", "{424A6D96-37EE-4456-8347-08AB425C8DBE}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution + dev\PushNotifications\PushNotifications.vcxitems*{103c0c23-7ba8-4d44-a63c-83488e2e3a81}*SharedItemsImports = 9 dev\UndockedRegFreeWinRT\UndockedRegFreeWinRT.vcxitems*{56371ca6-144b-4989-a4e9-391ad4fa7651}*SharedItemsImports = 9 test\inc\inc.vcxitems*{7c502995-59c3-483b-86ba-815985353633}*SharedItemsImports = 4 test\inc\inc.vcxitems*{8e52d7ea-a200-4a6b-ba74-8efb49468caf}*SharedItemsImports = 4 @@ -435,6 +444,75 @@ Global {A3FBA80D-5B35-471F-9A45-DB4B29E195B9}.Release|x86.ActiveCfg = Release|x86 {A3FBA80D-5B35-471F-9A45-DB4B29E195B9}.Release|x86.Build.0 = Release|x86 {A3FBA80D-5B35-471F-9A45-DB4B29E195B9}.Release|x86.Deploy.0 = Release|x86 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|Any CPU.ActiveCfg = Debug|Win32 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|Any CPU.Build.0 = Debug|Win32 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|ARM.ActiveCfg = Debug|Win32 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|ARM.Build.0 = Debug|Win32 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|ARM64.ActiveCfg = Debug|Win32 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|ARM64.Build.0 = Debug|Win32 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|x64.ActiveCfg = Debug|x64 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|x64.Build.0 = Debug|x64 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|x86.ActiveCfg = Debug|Win32 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|x86.Build.0 = Debug|Win32 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|ARM.ActiveCfg = Debug|Win32 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|ARM64.ActiveCfg = Debug|Win32 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|x64.ActiveCfg = Debug|x64 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|x64.Build.0 = Debug|x64 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|x86.ActiveCfg = Debug|Win32 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|x86.Build.0 = Debug|Win32 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|Any CPU.ActiveCfg = Release|Win32 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|ARM.ActiveCfg = Release|Win32 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|ARM64.ActiveCfg = Release|Win32 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|x64.ActiveCfg = Release|x64 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|x64.Build.0 = Release|x64 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|x86.ActiveCfg = Release|Win32 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|x86.Build.0 = Release|Win32 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|Any CPU.ActiveCfg = Debug|Any CPU + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|Any CPU.Build.0 = Debug|Any CPU + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|Any CPU.Deploy.0 = Debug|Any CPU + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|ARM.ActiveCfg = Debug|ARM + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|ARM.Build.0 = Debug|ARM + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|ARM.Deploy.0 = Debug|ARM + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|ARM64.Build.0 = Debug|ARM64 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|ARM64.Deploy.0 = Debug|ARM64 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|x64.ActiveCfg = Debug|x64 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|x64.Build.0 = Debug|x64 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|x64.Deploy.0 = Debug|x64 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|x86.ActiveCfg = Debug|x86 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|x86.Build.0 = Debug|x86 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|x86.Deploy.0 = Debug|x86 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|ARM.ActiveCfg = Debug|ARM + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|ARM.Build.0 = Debug|ARM + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|ARM.Deploy.0 = Debug|ARM + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|ARM64.Build.0 = Debug|ARM64 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|x64.ActiveCfg = Debug|x64 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|x64.Build.0 = Debug|x64 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|x64.Deploy.0 = Debug|x64 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|x86.ActiveCfg = Debug|x86 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|x86.Build.0 = Debug|x86 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|x86.Deploy.0 = Debug|x86 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|Any CPU.Build.0 = Release|Any CPU + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|Any CPU.Deploy.0 = Release|Any CPU + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|ARM.ActiveCfg = Release|ARM + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|ARM.Build.0 = Release|ARM + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|ARM.Deploy.0 = Release|ARM + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|ARM64.ActiveCfg = Release|ARM64 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|ARM64.Build.0 = Release|ARM64 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|ARM64.Deploy.0 = Release|ARM64 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|x64.ActiveCfg = Release|x64 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|x64.Build.0 = Release|x64 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|x64.Deploy.0 = Release|x64 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|x86.ActiveCfg = Release|x86 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|x86.Build.0 = Release|x86 + {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|x86.Deploy.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -474,6 +552,10 @@ Global {A657A14D-910D-43F3-9994-DAB0E22C4530} = {448ED2E5-0B37-4D97-9E6B-8C10A507976A} {8E52D7EA-A200-4A6B-BA74-8EFB49468CAF} = {AC5FFC80-92FE-4933-BED2-EC5519AC4440} {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} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4B3D7591-CFEC-4762-9A07-ABE99938FB77} diff --git a/dev/AppLifecycle/AppInstance.cpp b/dev/AppLifecycle/AppInstance.cpp index cb80749785..5c975d7d3f 100644 --- a/dev/AppLifecycle/AppInstance.cpp +++ b/dev/AppLifecycle/AppInstance.cpp @@ -11,6 +11,7 @@ #include "FileActivatedEventArgs.h" #include "Association.h" #include "ExtensionContract.h" +#include "GetRawNotificationEventArgs.h" using namespace winrt; using namespace winrt::Windows::Foundation; @@ -311,11 +312,21 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation if (HasIdentity()) { - auto args = winrt::Windows::ApplicationModel::AppInstance::GetActivatedEventArgs(); - if (args) + + auto pushArgs = GetRawNotificationEventArgs::GetRawNotificationEventArgs(); + if (pushArgs) { - data = args.as(); - kind = static_cast(args.Kind()); + data = pushArgs; + kind = ExtendedActivationKind::Push; + } + else + { + auto args = winrt::Windows::ApplicationModel::AppInstance::GetActivatedEventArgs(); + if (args) + { + data = args.as(); + kind = static_cast(args.Kind()); + } } } else diff --git a/dev/AppLifecycle/AppLifecycle.idl b/dev/AppLifecycle/AppLifecycle.idl index 92a0a68519..167f761450 100644 --- a/dev/AppLifecycle/AppLifecycle.idl +++ b/dev/AppLifecycle/AppLifecycle.idl @@ -50,7 +50,7 @@ namespace Microsoft.Windows.AppLifecycle PrintSupportSettingsUI, PhoneCallActivation, VpnForeground, - + Push // NOTE: Values below 5000 are designated for the platform. The above list is kept in sync with // Windows.ApplicationModel.Activation.ActivationKind. }; diff --git a/dev/ProjectReunion_DLL/ProjectReunion_DLL.vcxproj b/dev/ProjectReunion_DLL/ProjectReunion_DLL.vcxproj index 0456de19ba..48738d0deb 100644 --- a/dev/ProjectReunion_DLL/ProjectReunion_DLL.vcxproj +++ b/dev/ProjectReunion_DLL/ProjectReunion_DLL.vcxproj @@ -107,6 +107,7 @@ + diff --git a/dev/PushNotifications/GetRawNotificationEventArgs.h b/dev/PushNotifications/GetRawNotificationEventArgs.h new file mode 100644 index 0000000000..8796ecb92f --- /dev/null +++ b/dev/PushNotifications/GetRawNotificationEventArgs.h @@ -0,0 +1,32 @@ +#include +#include "PushNotificationReceivedEventArgs.h" +#include "externs.h" + +using namespace winrt; +using namespace winrt::Windows::Foundation; +constexpr PCWSTR pushServerArgument = L"-ReunionPushServer"; + +namespace GetRawNotificationEventArgs +{ + static Windows::Foundation::IInspectable GetRawNotificationEventArgs() + { + winrt::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs args = nullptr; + + std::wstring commandLineArgs = GetCommandLine(); + auto found = commandLineArgs.find(pushServerArgument, 0); + if (found != std::wstring::npos) + { + { + auto lock = g_lock.lock(); + THROW_HR_IF_NULL_MSG(E_UNEXPECTED, g_waitHandleForArgs, "PushNotificationManager::RegisterActivator has not been called."); + } + + if (WaitForSingleObject(g_waitHandleForArgs.get(), 1000) == WAIT_OBJECT_0) + { + auto lock = g_lock.lock(); + std::swap(args, g_activatedEventArgs); + } + } + return args; + } +} diff --git a/dev/PushNotifications/PushNotificationActivationInfo.cpp b/dev/PushNotifications/PushNotificationActivationInfo.cpp new file mode 100644 index 0000000000..82c71d48dc --- /dev/null +++ b/dev/PushNotifications/PushNotificationActivationInfo.cpp @@ -0,0 +1,41 @@ +#include "pch.h" +#include "PushNotificationActivationInfo.h" +#include "Microsoft.Windows.PushNotifications.PushNotificationActivationInfo.g.cpp" + +#include + +namespace winrt +{ + using namespace Microsoft::Windows::PushNotifications; + using namespace Windows::ApplicationModel::Background; +} + +namespace winrt::Microsoft::Windows::PushNotifications::implementation +{ + PushNotificationActivationInfo::PushNotificationActivationInfo(winrt::PushNotificationRegistrationKind const& kind, winrt::guid const& taskClsid) + { + m_kind = kind; + m_taskClsid = taskClsid; + } + winrt::guid PushNotificationActivationInfo::TaskClsid() + { + auto lock = m_lock.lock_shared(); + return m_taskClsid; + } + + winrt::PushNotificationRegistrationKind PushNotificationActivationInfo::Kind() + { + auto lock = m_lock.lock_shared(); + return m_kind; + } + winrt::com_array PushNotificationActivationInfo::GetConditions() + { + auto lock = m_lock.lock_shared(); + return winrt::com_array(m_backgroundConditions.begin(), m_backgroundConditions.end()); + } + void PushNotificationActivationInfo::SetConditions(array_view conditions) + { + auto lock = m_lock.lock_exclusive(); + m_backgroundConditions = winrt::com_array(conditions.begin(), conditions.end()); + } +} diff --git a/dev/PushNotifications/PushNotificationActivationInfo.h b/dev/PushNotifications/PushNotificationActivationInfo.h new file mode 100644 index 0000000000..4e10a3bead --- /dev/null +++ b/dev/PushNotifications/PushNotificationActivationInfo.h @@ -0,0 +1,28 @@ +#pragma once +#include "Microsoft.Windows.PushNotifications.PushNotificationActivationInfo.g.h" + +namespace winrt::Microsoft::Windows::PushNotifications::implementation +{ + struct PushNotificationActivationInfo : PushNotificationActivationInfoT + { + PushNotificationActivationInfo() = default; + + PushNotificationActivationInfo(Microsoft::Windows::PushNotifications::PushNotificationRegistrationKind const& kind, winrt::guid const& taskClsid); + winrt::guid TaskClsid(); + Microsoft::Windows::PushNotifications::PushNotificationRegistrationKind Kind(); + winrt::com_array GetConditions(); + void SetConditions(array_view conditions); + + private: + Microsoft::Windows::PushNotifications::PushNotificationRegistrationKind m_kind; + winrt::guid m_taskClsid; + winrt::com_array m_backgroundConditions{}; + wil::srwlock m_lock; + }; +} +namespace winrt::Microsoft::Windows::PushNotifications::factory_implementation +{ + struct PushNotificationActivationInfo : PushNotificationActivationInfoT + { + }; +} diff --git a/dev/PushNotifications/PushNotificationBackgroundTask.cpp b/dev/PushNotifications/PushNotificationBackgroundTask.cpp new file mode 100644 index 0000000000..505ee44ff6 --- /dev/null +++ b/dev/PushNotifications/PushNotificationBackgroundTask.cpp @@ -0,0 +1,25 @@ +#pragma once + +#include "pch.h" + +#include "PushNotificationBackgroundTask.h" + +#include +#include "PushNotificationReceivedEventArgs.h" +#include "externs.h" + +namespace winrt +{ + using namespace Windows::ApplicationModel::Background; + using namespace Microsoft::Windows::PushNotifications; +} + +wil::unique_handle g_waitHandleForArgs; +winrt::PushNotificationReceivedEventArgs g_activatedEventArgs{ nullptr }; + +void PushNotificationBackgroundTask::Run(winrt::IBackgroundTaskInstance taskInstance) +{ + SetEvent(g_waitHandleForArgs.get()); + auto lock = g_lock.lock(); + g_activatedEventArgs = winrt::PushNotificationReceivedEventArgs::CreateFromBackgroundTaskInstance(taskInstance); +} diff --git a/dev/PushNotifications/PushNotificationBackgroundTask.h b/dev/PushNotifications/PushNotificationBackgroundTask.h new file mode 100644 index 0000000000..31064900d1 --- /dev/null +++ b/dev/PushNotifications/PushNotificationBackgroundTask.h @@ -0,0 +1,28 @@ +#include + +struct PushNotificationBackgroundTask : winrt::implements +{ + PushNotificationBackgroundTask() {} + + void Run(winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance taskInstance); + + void OnCanceled( + winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance /*taskInstance*/, + winrt::Windows::ApplicationModel::Background::BackgroundTaskCancellationReason /*cancellationReason*/) + { + } +}; + +struct PushNotificationBackgroundTaskFactory : 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/PushNotificationChannel.cpp b/dev/PushNotifications/PushNotificationChannel.cpp new file mode 100644 index 0000000000..4b10c84a3c --- /dev/null +++ b/dev/PushNotifications/PushNotificationChannel.cpp @@ -0,0 +1,68 @@ +#include "pch.h" +#include "PushNotificationChannel.h" +#include "Microsoft.Windows.PushNotifications.PushNotificationChannel.g.cpp" +#include +#include + +namespace winrt +{ + using namespace Windows::Networking::PushNotifications; + using namespace Windows::Foundation; +} + +namespace winrt::Microsoft::Windows::PushNotifications::implementation +{ + // Need static handler/lock to keep alive upon channel request completion + winrt::TypedEventHandler< + Microsoft::Windows::PushNotifications::PushNotificationChannel, + Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs> s_typedEventHandler; + wil::srwlock s_lock; + + PushNotificationChannel::PushNotificationChannel(winrt::PushNotificationChannel const& channel) + { + m_channel = channel; + } + winrt::Uri PushNotificationChannel::Uri() + { + auto lock = s_lock.lock_shared(); + return winrt::Uri{ m_channel.Uri() }; + } + winrt::DateTime PushNotificationChannel::ExpirationTime() + { + auto lock = s_lock.lock_shared(); + return m_channel.ExpirationTime(); + } + void PushNotificationChannel::Close() + { + auto lock = s_lock.lock_shared(); + m_channel.Close(); + } + + winrt::event_token PushNotificationChannel::PushReceived(winrt::TypedEventHandler const& handler) + { + + winrt::TypedEventHandler< + winrt::PushNotificationChannel, + winrt::PushNotificationReceivedEventArgs> typedEventHandler + ([&]( + winrt::PushNotificationChannel channel, + winrt::PushNotificationReceivedEventArgs args) + { + PushNotificationReceivedEventArgs pushArgs = + PushNotificationReceivedEventArgs::CreateFromPushNotificationReceivedEventArgs(args); + auto lock = s_lock.lock_shared(); + s_typedEventHandler(*this, pushArgs); + }); + + auto lock = s_lock.lock_exclusive(); + s_typedEventHandler = handler; + return m_channel.PushNotificationReceived(typedEventHandler); + } + + void PushNotificationChannel::PushReceived(winrt::event_token const& token) noexcept + { + auto lock = s_lock.lock_exclusive(); + s_typedEventHandler = nullptr; + m_channel.PushNotificationReceived(token); + } +} diff --git a/dev/PushNotifications/PushNotificationChannel.h b/dev/PushNotifications/PushNotificationChannel.h new file mode 100644 index 0000000000..8a53db7db2 --- /dev/null +++ b/dev/PushNotifications/PushNotificationChannel.h @@ -0,0 +1,28 @@ +#pragma once +#include "Microsoft.Windows.PushNotifications.PushNotificationChannel.g.h" + +namespace winrt::Microsoft::Windows::PushNotifications::implementation +{ + struct PushNotificationChannel : PushNotificationChannelT + { + PushNotificationChannel() = default; + + PushNotificationChannel(winrt::Windows::Networking::PushNotifications::PushNotificationChannel const& channel); + winrt::Windows::Foundation::Uri Uri(); + winrt::Windows::Foundation::DateTime ExpirationTime(); + void Close(); + + winrt::event_token PushReceived(winrt::Windows::Foundation::TypedEventHandler const& handler); + void PushReceived(winrt::event_token const& token) noexcept; + + private: + winrt::Windows::Networking::PushNotifications::PushNotificationChannel m_channel{ nullptr }; + + }; +} +namespace winrt::Microsoft::Windows::PushNotifications::factory_implementation +{ + struct PushNotificationChannel : PushNotificationChannelT + { + }; +} diff --git a/dev/PushNotifications/PushNotificationCreateChannelResult.cpp b/dev/PushNotifications/PushNotificationCreateChannelResult.cpp new file mode 100644 index 0000000000..1d96b1426c --- /dev/null +++ b/dev/PushNotifications/PushNotificationCreateChannelResult.cpp @@ -0,0 +1,25 @@ +#include "pch.h" +#include "PushNotificationCreateChannelResult.h" +#include "Microsoft.Windows.PushNotifications.PushNotificationCreateChannelResult.g.cpp" + +namespace winrt::Microsoft::Windows::PushNotifications::implementation +{ + PushNotificationCreateChannelResult::PushNotificationCreateChannelResult(PushNotificationChannel const& channel, winrt::hresult const& extendedError, PushNotificationChannelStatus const& status) + { + m_channel = channel; + m_extendedError = extendedError; + m_status = status; + } + PushNotificationChannel PushNotificationCreateChannelResult::Channel() + { + return m_channel; + } + winrt::hresult PushNotificationCreateChannelResult::ExtendedError() + { + return m_extendedError; + } + PushNotificationChannelStatus PushNotificationCreateChannelResult::Status() + { + return m_status; + } +} diff --git a/dev/PushNotifications/PushNotificationCreateChannelResult.h b/dev/PushNotifications/PushNotificationCreateChannelResult.h new file mode 100644 index 0000000000..be50222ef8 --- /dev/null +++ b/dev/PushNotifications/PushNotificationCreateChannelResult.h @@ -0,0 +1,26 @@ +#pragma once +#include "Microsoft.Windows.PushNotifications.PushNotificationCreateChannelResult.g.h" + +namespace winrt::Microsoft::Windows::PushNotifications::implementation +{ + struct PushNotificationCreateChannelResult : PushNotificationCreateChannelResultT + { + PushNotificationCreateChannelResult() = default; + + PushNotificationCreateChannelResult(Microsoft::Windows::PushNotifications::PushNotificationChannel const& channel, hresult const& extendedError, Microsoft::Windows::PushNotifications::PushNotificationChannelStatus const& status); + Microsoft::Windows::PushNotifications::PushNotificationChannel Channel(); + winrt::hresult ExtendedError(); + Microsoft::Windows::PushNotifications::PushNotificationChannelStatus Status(); + + private: + Microsoft::Windows::PushNotifications::PushNotificationChannel m_channel{ nullptr }; + winrt::hresult m_extendedError; + Microsoft::Windows::PushNotifications::PushNotificationChannelStatus m_status; + }; +} +namespace winrt::Microsoft::Windows::PushNotifications::factory_implementation +{ + struct PushNotificationCreateChannelResult : PushNotificationCreateChannelResultT + { + }; +} diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp new file mode 100644 index 0000000000..824e147918 --- /dev/null +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -0,0 +1,263 @@ +#include "pch.h" + +#include "PushNotificationManager.h" +#include "Microsoft.Windows.PushNotifications.PushNotificationManager.g.cpp" + +#include "PushNotificationCreateChannelResult.h" + +#include +#include +#include "PushNotificationBackgroundTask.h" + +#include +#include +#include "PushNotificationChannel.h" +#include "externs.h" + +constexpr PCWSTR backgroundTaskName = L"PushBackgroundTaskName"; + +namespace winrt +{ + using namespace Windows::ApplicationModel::Background; + using namespace Windows::Networking::PushNotifications; + using namespace Windows::Foundation; +} + +wil::critical_section g_lock; + +namespace winrt::Microsoft::Windows::PushNotifications::implementation +{ + inline constexpr std::uint32_t c_maxBackoffSeconds{ 960 }; + inline constexpr std::uint32_t c_minBackoffSeconds{ 30 }; + + const HRESULT WNP_E_NOT_CONNECTED = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x880403E8L); + const HRESULT WNP_E_RECONNECTING = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x880403E9L); + const HRESULT WNP_E_BIND_USER_BUSY = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x880403FEL); + + bool PushNotificationManager::isChannelRequestRetryable(const hresult& hr) + { + switch (hr) + { + case HRESULT_FROM_WIN32(ERROR_TIMEOUT): + case WNP_E_NOT_CONNECTED: + case WPN_E_OUTSTANDING_CHANNEL_REQUEST: + case WNP_E_RECONNECTING: + case WNP_E_BIND_USER_BUSY: + case RPC_S_SERVER_UNAVAILABLE: + return true; + default: + return false; + } + } + + inline bool IsPackagedProcess() + { + wchar_t packageFullName[PACKAGE_FULL_NAME_MAX_LENGTH + 1] = {}; + + UINT32 packageFullNameLength = static_cast(ARRAYSIZE(packageFullName)); + + const auto packagedProcessHResult = ::GetCurrentPackageFullName(&packageFullNameLength, packageFullName); + + if (packagedProcessHResult == APPMODEL_ERROR_NO_PACKAGE) + { + return false; + } + + THROW_IF_FAILED(packagedProcessHResult); + + return true; + } + + winrt::IAsyncOperationWithProgress PushNotificationManager::CreateChannelAsync(winrt::guid remoteId) + { + static bool s_remoteIdInProgress; + static wil::critical_section s_lock; + + THROW_HR_IF(E_INVALIDARG, (remoteId == winrt::guid())); + + // API supports channel requests only for packaged applications for v0.8 version + THROW_HR_IF(E_NOTIMPL, (IsPackagedProcess() == false)); + + winrt::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult channelResult{ nullptr }; + { + auto lock = s_lock.lock(); + if (s_remoteIdInProgress == false) + { + s_remoteIdInProgress = true; + } + else + { + channelResult = winrt::make( + nullptr, WPN_E_OUTSTANDING_CHANNEL_REQUEST, PushNotificationChannelStatus::CompletedFailure); + co_return channelResult; + } + } + + auto scopeExit = wil::scope_exit([&]() + { + auto lock = s_lock.lock(); + s_remoteIdInProgress = false; + }); + + auto cancellation{ co_await winrt::get_cancellation_token() }; + + cancellation.enable_propagation(true); + + // Allow to register the progress and complete handler + co_await resume_background(); + + auto progress{ co_await winrt::get_progress_token() }; + + uint8_t retryCount = 0; + winrt::hresult channelRequestResult = E_PENDING; + PushNotificationChannelStatus status = PushNotificationChannelStatus::InProgress; + + PushNotificationCreateChannelStatus + channelStatus = { channelRequestResult, status, retryCount }; + + progress(channelStatus); + + PushNotificationChannelManager channelManager{}; + winrt::PushNotificationChannel pushChannelReceived{ nullptr }; + + for (auto backOffTimeInSeconds = c_minBackoffSeconds; backOffTimeInSeconds <= c_maxBackoffSeconds * 2; backOffTimeInSeconds *= 2) + { + try + { + pushChannelReceived = co_await channelManager.CreatePushNotificationChannelForApplicationAsync(); + channelRequestResult = S_OK; + status = PushNotificationChannelStatus::CompletedSuccess; + break; + } + catch (...) + { + + auto channelRequestException = hresult_error(to_hresult(), take_ownership_from_abi); + + if ((backOffTimeInSeconds <= c_maxBackoffSeconds) && isChannelRequestRetryable(channelRequestException.code())) + { + channelStatus.extendedError = channelRequestException.code(); + channelStatus.status = PushNotificationChannelStatus::InProgressRetry; + channelStatus.retryCount = ++retryCount; + + progress(channelStatus); + } + else + { + channelRequestResult = channelRequestException.code(); + status = PushNotificationChannelStatus::CompletedFailure; + break; + } + } + + co_await winrt::resume_after(std::chrono::seconds(backOffTimeInSeconds)); + } + + + if (status == PushNotificationChannelStatus::CompletedSuccess) + { + // Returns a com_ptr to the implementation type + auto pushChannel = + winrt::make_self(pushChannelReceived); + + channelResult = winrt::make( + *(pushChannel.get()), + channelRequestResult, + status); + } + else if (status == PushNotificationChannelStatus::CompletedFailure) + { + channelResult = winrt::make( + nullptr, + channelRequestResult, + status); + } + + co_return channelResult; + } + + PushNotificationRegistrationToken PushNotificationManager::RegisterActivator(PushNotificationActivationInfo const& details) + { + winrt::guid taskClsid = details.TaskClsid(); + DWORD cookie = 0; + BackgroundTaskRegistration registeredTask = nullptr; + + if (WI_IsFlagSet(details.Kind(), PushNotificationRegistrationKind::PushTrigger)) + { + bool taskRegistered = false; + for (auto task : BackgroundTaskRegistration::AllTasks()) + { + if (task.Value().Name() == backgroundTaskName) + { + taskRegistered = true; + break; + } + } + + if (!taskRegistered) + { + BackgroundTaskBuilder builder; + builder.Name(backgroundTaskName); + + PushNotificationTrigger trigger{}; + builder.SetTrigger(trigger); + + if (taskClsid != winrt::guid()) + { + auto builder5 = builder.try_as(); + if (IsPackagedProcess() && builder5) + { + builder5.SetTaskEntryPointClsid(taskClsid); + winrt::com_array conditions = details.GetConditions(); + for (auto condition : conditions) + { + builder.AddCondition(condition); + } + } + } + + registeredTask = builder.Register(); + } + } + + if (WI_IsFlagSet(details.Kind(), PushNotificationRegistrationKind::ComActivator)) + { + if (taskClsid != winrt::guid()) + { + { + auto lock = g_lock.lock(); + // Define handle that will be set during background task execution + g_waitHandleForArgs = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + } + + THROW_IF_FAILED(::CoRegisterClassObject( + taskClsid, + winrt::make().get(), + CLSCTX_LOCAL_SERVER, + REGCLS_MULTIPLEUSE, + &cookie)); + } + } + return PushNotificationRegistrationToken{ cookie, registeredTask }; + } + + void PushNotificationManager::UnregisterActivator(PushNotificationRegistrationToken const& token, PushNotificationRegistrationKind const& kind) + { + + if (WI_IsFlagSet(kind, PushNotificationRegistrationKind::PushTrigger)) + { + for (auto task : BackgroundTaskRegistration::AllTasks()) + { + if (task.Value().Name() == backgroundTaskName) + { + task.Value().Unregister(false /*cancel task*/); + } + } + } + + if (WI_IsFlagSet(kind, PushNotificationRegistrationKind::ComActivator) && (token.Cookie() != 0)) + { + THROW_IF_FAILED(::CoRevokeClassObject(static_cast(token.Cookie()))); + } + } +} diff --git a/dev/PushNotifications/PushNotificationManager.h b/dev/PushNotifications/PushNotificationManager.h new file mode 100644 index 0000000000..403db2c649 --- /dev/null +++ b/dev/PushNotifications/PushNotificationManager.h @@ -0,0 +1,24 @@ +#pragma once +#include "Microsoft.Windows.PushNotifications.PushNotificationManager.g.h" + +namespace winrt::Microsoft::Windows::PushNotifications::implementation +{ + struct PushNotificationManager + { + PushNotificationManager() = default; + + static Microsoft::Windows::PushNotifications::PushNotificationRegistrationToken RegisterActivator(Microsoft::Windows::PushNotifications::PushNotificationActivationInfo const& details); + static void UnregisterActivator(Microsoft::Windows::PushNotifications::PushNotificationRegistrationToken const& token, Microsoft::Windows::PushNotifications::PushNotificationRegistrationKind const& kind); + + static winrt::Windows::Foundation::IAsyncOperationWithProgress CreateChannelAsync(winrt::guid remoteId); + + private: + static bool isChannelRequestRetryable(const winrt::hresult& hrException); + }; +} +namespace winrt::Microsoft::Windows::PushNotifications::factory_implementation +{ + struct PushNotificationManager : PushNotificationManagerT + { + }; +} diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp new file mode 100644 index 0000000000..0562562b65 --- /dev/null +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp @@ -0,0 +1,118 @@ +#include "pch.h" + +#include +#include +#include + +#include "PushNotificationReceivedEventArgs.h" +#include "Microsoft.Windows.PushNotifications.PushNotificationReceivedEventArgs.g.cpp" +#include + +namespace winrt +{ + using namespace Windows::ApplicationModel::Background; + using namespace Windows::Storage::Streams; + using namespace Windows::Networking::PushNotifications; +} + +namespace winrt::Microsoft::Windows::PushNotifications::implementation +{ + PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::IBackgroundTaskInstance const& backgroundTask) + { + m_backgroundTaskInstance = backgroundTask; + + // Need to process the RawNotification payload here because TriggerDetails is set to nullptr leaving IBackgroundTaskInstance::Run + auto triggerDetails = m_backgroundTaskInstance.TriggerDetails(); + RawNotification rawNotification = triggerDetails.as(); + + IBuffer rawContentAsBuffer = rawNotification.ContentBytes(); + DataReader dataReader = DataReader::FromBuffer(rawContentAsBuffer); + + m_backgroundPayload = winrt::com_array(rawContentAsBuffer.Length()); + dataReader.ReadBytes(m_backgroundPayload); + } + + PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::PushNotificationReceivedEventArgs const& args) + { + m_args = args; + } + + winrt::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs PushNotificationReceivedEventArgs::CreateFromBackgroundTaskInstance(winrt::IBackgroundTaskInstance const& backgroundTask) + { + return winrt::make(backgroundTask); + } + + winrt::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs PushNotificationReceivedEventArgs::CreateFromPushNotificationReceivedEventArgs(winrt::PushNotificationReceivedEventArgs const& args) + { + return winrt::make(args); + } + + winrt::com_array PushNotificationReceivedEventArgs::Payload() + { + auto lock = m_lock.lock_shared(); + winrt::com_array payload{}; + if (m_args) + { + RawNotification rawNotification = m_args.RawNotification(); + + IBuffer rawContentAsBuffer = rawNotification.ContentBytes(); + DataReader dataReader = DataReader::FromBuffer(rawContentAsBuffer); + + payload = winrt::com_array(rawContentAsBuffer.Length()); + dataReader.ReadBytes(payload); + } + else if (m_backgroundTaskInstance) + { + return winrt::com_array(m_backgroundPayload.begin(), m_backgroundPayload.end()); + } + return payload; + } + + winrt::BackgroundTaskDeferral PushNotificationReceivedEventArgs::GetDeferral() + { + auto lock = m_lock.lock_shared(); + if (m_backgroundTaskInstance) + { + return m_backgroundTaskInstance.GetDeferral(); + } + return nullptr; + } + + winrt::event_token PushNotificationReceivedEventArgs::Canceled(winrt::BackgroundTaskCanceledEventHandler const& handler) + { + { + auto lock = m_lock.lock_shared(); + if (m_backgroundTaskInstance) + { + return m_backgroundTaskInstance.Canceled(handler); + } + } + + return winrt::event_token{}; + } + void PushNotificationReceivedEventArgs::Canceled(winrt::event_token const& token) noexcept + { + auto lock = m_lock.lock_shared(); + if (m_backgroundTaskInstance) + { + m_backgroundTaskInstance.Canceled(token); + } + } + bool PushNotificationReceivedEventArgs::Handled() + { + auto lock = m_lock.lock_shared(); + if (m_args) + { + return m_args.Cancel(); + } + return false; + } + void PushNotificationReceivedEventArgs::Handled(bool value) + { + auto lock = m_lock.lock_shared(); + if (m_args) + { + m_args.Cancel(value); + } + } +} diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.h b/dev/PushNotifications/PushNotificationReceivedEventArgs.h new file mode 100644 index 0000000000..e006d72a54 --- /dev/null +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.h @@ -0,0 +1,32 @@ +#pragma once +#include "Microsoft.Windows.PushNotifications.PushNotificationReceivedEventArgs.g.h" + +namespace winrt::Microsoft::Windows::PushNotifications::implementation +{ + struct PushNotificationReceivedEventArgs : PushNotificationReceivedEventArgsT + { + PushNotificationReceivedEventArgs(winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance const& backgroundTask); + PushNotificationReceivedEventArgs(winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs const& args); + + static Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs CreateFromBackgroundTaskInstance(winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance const& backgroundTask); + static Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs CreateFromPushNotificationReceivedEventArgs(winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs const& args); + winrt::com_array Payload(); + winrt::Windows::ApplicationModel::Background::BackgroundTaskDeferral GetDeferral(); + winrt::event_token Canceled(winrt::Windows::ApplicationModel::Background::BackgroundTaskCanceledEventHandler const& handler); + void Canceled(winrt::event_token const& token) noexcept; + bool Handled(); + void Handled(bool value); + + private: + winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance m_backgroundTaskInstance = nullptr; + winrt::com_array m_backgroundPayload{}; + winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs m_args = nullptr; + wil::srwlock m_lock; + }; +} +namespace winrt::Microsoft::Windows::PushNotifications::factory_implementation +{ + struct PushNotificationReceivedEventArgs : PushNotificationReceivedEventArgsT + { + }; +} diff --git a/dev/PushNotifications/PushNotificationRegistrationToken.cpp b/dev/PushNotifications/PushNotificationRegistrationToken.cpp new file mode 100644 index 0000000000..60342fa4d6 --- /dev/null +++ b/dev/PushNotifications/PushNotificationRegistrationToken.cpp @@ -0,0 +1,24 @@ +#include "pch.h" +#include "PushNotificationRegistrationToken.h" +#include "Microsoft.Windows.PushNotifications.PushNotificationRegistrationToken.g.cpp" + +#include + +namespace winrt::Microsoft::Windows::PushNotifications::implementation +{ + PushNotificationRegistrationToken::PushNotificationRegistrationToken(uint64_t cookie, winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration const& taskRegistration) + { + m_cookie = cookie; + m_taskRegistration = taskRegistration; + } + uint64_t PushNotificationRegistrationToken::Cookie() + { + auto lock = m_lock.lock_shared(); + return m_cookie; + } + winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration PushNotificationRegistrationToken::TaskRegistration() + { + auto lock = m_lock.lock_shared(); + return m_taskRegistration; + } +} diff --git a/dev/PushNotifications/PushNotificationRegistrationToken.h b/dev/PushNotifications/PushNotificationRegistrationToken.h new file mode 100644 index 0000000000..c164ac93c0 --- /dev/null +++ b/dev/PushNotifications/PushNotificationRegistrationToken.h @@ -0,0 +1,25 @@ +#pragma once +#include "Microsoft.Windows.PushNotifications.PushNotificationRegistrationToken.g.h" + +namespace winrt::Microsoft::Windows::PushNotifications::implementation +{ + struct PushNotificationRegistrationToken : PushNotificationRegistrationTokenT + { + PushNotificationRegistrationToken() = default; + + PushNotificationRegistrationToken(uint64_t cookie, winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration const& taskRegistration); + uint64_t Cookie(); + winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration TaskRegistration(); + + private: + uint64_t m_cookie; + winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration m_taskRegistration = nullptr; + wil::srwlock m_lock; + }; +} +namespace winrt::Microsoft::Windows::PushNotifications::factory_implementation +{ + struct PushNotificationRegistrationToken : PushNotificationRegistrationTokenT + { + }; +} diff --git a/dev/PushNotifications/PushNotifications.idl b/dev/PushNotifications/PushNotifications.idl new file mode 100644 index 0000000000..dac0a3dd3b --- /dev/null +++ b/dev/PushNotifications/PushNotifications.idl @@ -0,0 +1,134 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +namespace Microsoft.Windows.PushNotifications +{ + // Event args for the Push payload. + runtimeclass PushNotificationReceivedEventArgs + { + // Initialize using the IBackgroundInstance: used specifically for the Background Activation scenario + static PushNotificationReceivedEventArgs CreateFromBackgroundTaskInstance(Windows.ApplicationModel.Background.IBackgroundTaskInstance backgroundTask); + +// Initialize using the PushNotificationEventArgs from Windows: used specifically for in-memory event handling when app is already in foreground +static PushNotificationReceivedEventArgs CreateFromPushNotificationReceivedEventArgs(Windows.Networking.PushNotifications.PushNotificationReceivedEventArgs args); + +// The Push payload +byte[] Payload { get; }; + +// Gets a deferral to run under specific modes like low power mode +Windows.ApplicationModel.Background.BackgroundTaskDeferral GetDeferral(); + +// Subscribe to Cancelled event handler to be signalled when resource policies are no longer true like 30s wallclock timer +event Windows.ApplicationModel.Background.BackgroundTaskCanceledEventHandler Canceled; + +// Set to true to prevent proceeding launch due to Background Activation: false by default +Boolean Handled; +}; + +[flags] +enum PushNotificationRegistrationKind +{ + PushTrigger = 0x1, // Registers a Push Trigger with Background Infrastructure + ComActivator = 0x2, // Registers the Project Reunion Background Task component as an InProc COM server +}; + +// An abstraction over the activation Registration flow +runtimeclass PushNotificationActivationInfo +{ + // Initialize using a RegistrationKind 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 Project Reunion Background Task component will be Registered as an InProc COM server + PushNotificationActivationInfo(PushNotificationRegistrationKind kind, Guid taskClsid); + +// The CLSID associated with the Client COM server that Project Reunion will activate +Guid TaskClsid{ get; }; + +PushNotificationRegistrationKind Kind{ get; }; + +// The conditions under which Push Triggers would execute +Windows.ApplicationModel.Background.IBackgroundCondition[] GetConditions(); +void SetConditions(Windows.ApplicationModel.Background.IBackgroundCondition[] conditions); +}; + +enum PushNotificationChannelStatus +{ + InProgress, // The request is in progress and there is no retry operation + InProgressRetry, // The request is in progress and is in a backoff retry state. Check ExtendedError for HRESULT for retryable error. + CompletedSuccess, // The request completed successfully + CompletedFailure, // The request failed with some critical internal error. Check ExtendedError for HRESULT +}; + +// The PushNotificationChannel Progress result +struct PushNotificationCreateChannelStatus +{ + // The last extended error we failed Channel requests on that caused the inprogress retry status. S_OK if this is just progress status. + HRESULT extendedError; + + // Either InProgress or InProgressRetry status + PushNotificationChannelStatus status; + + // Total Retries so far + UInt32 retryCount; +}; + +runtimeclass PushNotificationChannel +{ + PushNotificationChannel(Windows.Networking.PushNotifications.PushNotificationChannel channel); + +// The Channel Uri for app to Post a notification to. +Windows.Foundation.Uri Uri { get; }; + +// Expiration of the Channel +Windows.Foundation.DateTime ExpirationTime { get; }; + +// Unsubscribes the channel +void Close(); + +// In-memory Event handler for Push Notifications +event Windows.Foundation.TypedEventHandler PushReceived; +} + +runtimeclass PushNotificationCreateChannelResult +{ + PushNotificationCreateChannelResult( + PushNotificationChannel channel, + HRESULT extendedError, + PushNotificationChannelStatus status); + +// The Push channel associated with the Result. Null if InProgress or completion failed +PushNotificationChannel Channel { get; }; + +// More detailed error code in addition to the ChannelStatus state. +HRESULT ExtendedError{ get; }; + +// The Status of the ChannelComplete operation +PushNotificationChannelStatus Status { get; }; +}; + +runtimeclass PushNotificationRegistrationToken +{ + PushNotificationRegistrationToken( + UInt64 cookie, + Windows.ApplicationModel.Background.BackgroundTaskRegistration taskRegistration); + +// The cookie from CoRegisterClassObject +UInt64 Cookie{ get; }; + +// The Registration token for the Push Trigger +Windows.ApplicationModel.Background.BackgroundTaskRegistration TaskRegistration { get; }; +}; + +static runtimeclass PushNotificationManager +{ + // Register an activator using an ActivationInfo context and return a RegistrationToken + static PushNotificationRegistrationToken RegisterActivator(PushNotificationActivationInfo details); + +// Unregister any activator if present using a token and registrationKind +// 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 +static void UnregisterActivator(PushNotificationRegistrationToken token, PushNotificationRegistrationKind kind); + +// Request a Push Channel with an encoded RemoteId from WNS. RemoteId is an AAD identifier GUID +static Windows.Foundation.IAsyncOperationWithProgress CreateChannelAsync(Guid remoteId); +}; +} diff --git a/dev/PushNotifications/PushNotifications.vcxitems b/dev/PushNotifications/PushNotifications.vcxitems new file mode 100644 index 0000000000..ae0ad30459 --- /dev/null +++ b/dev/PushNotifications/PushNotifications.vcxitems @@ -0,0 +1,39 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + {103c0c23-7ba8-4d44-a63c-83488e2e3a81} + + + + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dev/PushNotifications/externs.h b/dev/PushNotifications/externs.h new file mode 100644 index 0000000000..e0c7ddd8f8 --- /dev/null +++ b/dev/PushNotifications/externs.h @@ -0,0 +1,7 @@ +#pragma once +#include "pch.h" +#include "PushNotificationReceivedEventArgs.h" + +extern wil::unique_handle g_waitHandleForArgs; +extern winrt::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs g_activatedEventArgs; +extern wil::critical_section g_lock; diff --git a/test/DynamicDependency/data/Microsoft.ProjectReunion.Framework/appxmanifest.xml b/test/DynamicDependency/data/Microsoft.ProjectReunion.Framework/appxmanifest.xml index 4bff129ed7..06be6e91ae 100644 --- a/test/DynamicDependency/data/Microsoft.ProjectReunion.Framework/appxmanifest.xml +++ b/test/DynamicDependency/data/Microsoft.ProjectReunion.Framework/appxmanifest.xml @@ -51,6 +51,12 @@ + + + + + + diff --git a/test/TestApps/AppLifecycleTestPackage/AppLifecycleTestPackage.wapproj b/test/TestApps/AppLifecycleTestPackage/AppLifecycleTestPackage.wapproj index 4c5732991e..af6d65c595 100644 --- a/test/TestApps/AppLifecycleTestPackage/AppLifecycleTestPackage.wapproj +++ b/test/TestApps/AppLifecycleTestPackage/AppLifecycleTestPackage.wapproj @@ -58,12 +58,12 @@ ..\AppLifecycleTestApp\AppLifecycleTestApp.vcxproj true False - $(SolutionDir)temp\MSTest.pfx SHA256 True True $(Platform) 0 + 3A5485ABFA9FA31CC7DD1907102213D1ED1A0292 Always @@ -101,6 +101,7 @@ + diff --git a/test/TestApps/AppLifecycleTestPackage/Package.appxmanifest b/test/TestApps/AppLifecycleTestPackage/Package.appxmanifest index 65c897f26f..75ef8059fc 100644 --- a/test/TestApps/AppLifecycleTestPackage/Package.appxmanifest +++ b/test/TestApps/AppLifecycleTestPackage/Package.appxmanifest @@ -8,8 +8,8 @@ + Publisher="CN=WNP_Reunion" + Version="1.0.2.0" /> AppLifecycleTestPackage diff --git a/test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj b/test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj new file mode 100644 index 0000000000..620823cb70 --- /dev/null +++ b/test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj @@ -0,0 +1,177 @@ + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {5b2d17fe-c371-417f-860c-3d32397c2404} + PushNotificationsDemoApp + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + + + ..\..\..\BuildOutput\Release\x64\ProjectReunion_DLL\Microsoft.Windows.AppLifecycle.winmd + true + Microsoft.ProjectReunion.dll + + + ..\..\..\BuildOutput\Release\x64\ProjectReunion_DLL\Microsoft.Windows.PushNotifications.winmd + true + Microsoft.ProjectReunion.dll + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file diff --git a/test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj.filters b/test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj.filters new file mode 100644 index 0000000000..628b51e4d6 --- /dev/null +++ b/test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + + + Header Files + + + + + + \ No newline at end of file diff --git a/test/TestApps/PushNotificationsDemoApp/main.cpp b/test/TestApps/PushNotificationsDemoApp/main.cpp new file mode 100644 index 0000000000..2c9311b29f --- /dev/null +++ b/test/TestApps/PushNotificationsDemoApp/main.cpp @@ -0,0 +1,130 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. +#include "pch.h" +#include +#include +#include +#include // we need this for BackgroundTask APIs + +#define SIZE 26 + +using namespace winrt::Microsoft::Windows::AppLifecycle; +using namespace winrt::Microsoft::Windows::PushNotifications; +using namespace winrt; +using namespace winrt::Windows::Storage; +using namespace winrt::Windows::Storage::Streams; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::ApplicationModel::Activation; +using namespace winrt::Windows::ApplicationModel::Background; // BackgroundTask APIs + +time_t ltime; +char buf[SIZE]; + +void RequestChannel() +{ + // Register the AAD RemoteIdentifier for the App to receive Push + auto channelOperation = PushNotificationManager::CreateChannelAsync( + winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2")); + + // Setup the inprogress event handler + channelOperation.Progress( + []( + IAsyncOperationWithProgress const& sender, + PushNotificationCreateChannelStatus const& args) + { + if (args.status == PushNotificationChannelStatus::InProgress) + { + // This is basically a noop since it isn't really an error state + std::cout << "Channel request is in progress." << std::endl << std::endl; + } + else if (args.status == PushNotificationChannelStatus::InProgressRetry) + { + LOG_HR_MSG( + args.extendedError, + "The channel request is in back-off retry mode because of a retryable error! Expect delays in acquiring it. RetryCount = %d", + args.retryCount); + } + }); + + winrt::event_token pushToken; + + // Setup the completed event handler + channelOperation.Completed( + [&]( + IAsyncOperationWithProgress const& sender, + AsyncStatus const asyncStatus) + { + auto result = sender.GetResults(); + if (result.Status() == PushNotificationChannelStatus::CompletedSuccess) + { + auto channelUri = result.Channel().Uri(); + + std::cout << "channelUri: " << winrt::to_string(channelUri.ToString()) << std::endl << std::endl; + + auto channelExpiry = result.Channel().ExpirationTime(); + + // Register Push Event for Foreground + pushToken = result.Channel().PushReceived([&](const auto&, PushNotificationReceivedEventArgs args) + { + auto payload = args.Payload(); + + // Do stuff to process the raw payload + std::string payloadString(payload.begin(), payload.end()); + std::cout << "Push notification content received from FOREGROUND: " << payloadString << std::endl << std::endl; + args.Handled(true); + }); + } + else if (result.Status() == PushNotificationChannelStatus::CompletedFailure) + { + LOG_HR_MSG(result.ExtendedError(), "We hit a critical non-retryable error with channel request!"); + } + }); +} + +int main() +{ + time(<ime); + ctime_s(buf, sizeof buf, <ime); + std::cout << "Project Reunion Push Notification Test App: " << buf << std::endl; + + PushNotificationActivationInfo info( + PushNotificationRegistrationKind::PushTrigger | PushNotificationRegistrationKind::ComActivator, + winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2")); // same clsid as app manifest + + auto token = PushNotificationManager::RegisterActivator(info); + + auto args = AppInstance::GetCurrent().GetActivatedEventArgs(); + auto kind = args.Kind(); + if (kind == ExtendedActivationKind::Push) + { + PushNotificationReceivedEventArgs pushArgs = args.Data().as(); + + // Call GetDeferral to ensure that code runs in low power + auto deferral = pushArgs.GetDeferral(); + + auto payload = pushArgs.Payload(); + + // Do stuff to process the raw payload + std::string payloadString(payload.begin(), payload.end()); + std::cout << "Push notification content received from BACKGROUND: " << payloadString << std::endl << std::endl; + std::cout << "Press 'Enter' to exit the App." << std::endl; + std::cin.ignore(); + // Call Complete on the deferral as good practise: Needed mainly for low power usage + deferral.Complete(); + } + else if (kind == ExtendedActivationKind::Launch) + { + RequestChannel(); + std::cout << "Press 'Enter' at any time to exit App." << std::endl << std::endl; + std::cin.ignore(); + } + else if (kind == ExtendedActivationKind::ToastNotification) + { + std::cout << "ToastNotification received!" << std::endl << std::endl; + std::cout << "Press 'Enter' at any time to exit App." << std::endl << std::endl; + std::cin.ignore(); + } + + PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationKind::ComActivator); + return 0; +} diff --git a/test/TestApps/PushNotificationsDemoApp/packages.config b/test/TestApps/PushNotificationsDemoApp/packages.config new file mode 100644 index 0000000000..e8543f44a9 --- /dev/null +++ b/test/TestApps/PushNotificationsDemoApp/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/test/TestApps/PushNotificationsDemoApp/pch.cpp b/test/TestApps/PushNotificationsDemoApp/pch.cpp new file mode 100644 index 0000000000..1a6cb122e2 --- /dev/null +++ b/test/TestApps/PushNotificationsDemoApp/pch.cpp @@ -0,0 +1,3 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. +#include "pch.h" diff --git a/test/TestApps/PushNotificationsDemoApp/pch.h b/test/TestApps/PushNotificationsDemoApp/pch.h new file mode 100644 index 0000000000..f5e2c8d252 --- /dev/null +++ b/test/TestApps/PushNotificationsDemoApp/pch.h @@ -0,0 +1,19 @@ + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include diff --git a/test/TestApps/PushNotificationsDemoPackage/Images/LockScreenLogo.scale-200.png b/test/TestApps/PushNotificationsDemoPackage/Images/LockScreenLogo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..735f57adb5dfc01886d137b4e493d7e97cf13af3 GIT binary patch literal 1430 zcmaJ>TTC2P7~aKltDttVHYH6u8Io4i*}3fO&d$gd*bA_<3j~&e7%8(eXJLfhS!M@! zKrliY>>6yT4+Kr95$!DoD(Qn-5TP|{V_KS`k~E6(LGS@#`v$hQo&^^BKsw3HIsZBT z_y6C2n`lK@apunKojRQ^(_P}Mgewt$(^BBKCTZ;*xa?J3wQ7~@S0lUvbcLeq1Bg4o zH-bvQi|wt~L7q$~a-gDFP!{&TQfc3fX*6=uHv* zT&1&U(-)L%Xp^djI2?~eBF2cxC@YOP$+9d?P&h?lPy-9M2UT9fg5jKm1t$m#iWE{M zIf%q9@;fyT?0UP>tcw-bLkz;s2LlKl2qeP0w zECS7Ate+Awk|KQ+DOk;fl}Xsy4o^CY=pwq%QAAKKl628_yNPsK>?A>%D8fQG6IgdJ ztnxttBz#NI_a@fk7SU`WtrpsfZsNs9^0(2a z@C3#YO3>k~w7?2hipBf{#b6`}Xw1hlG$yi?;1dDs7k~xDAw@jiI*+tc;t2Lflg&bM)0!Y;0_@=w%`LW^8DsYpS#-bLOklX9r?Ei}TScw|4DbpW%+7 zFgAI)f51s}{y-eWb|vrU-Ya!GuYKP)J7z#*V_k^Xo>4!1Yqj*m)x&0L^tg3GJbVAJ zJ-Pl$R=NAabouV=^z_t;^K*0AvFs!vYU>_<|I^#c?>>CR<(T?=%{;U=aI*SbZADLH z&(f2wz_Y0??Tf|g;?|1Znw6}6U43Q#qNRwv1vp9uFn1)V#*4p&%$mP9x&15^OaBiDS(XppT|z^>;B{PLVEbS3IFYV yGvCsSX*m literal 0 HcmV?d00001 diff --git a/test/TestApps/PushNotificationsDemoPackage/Images/SplashScreen.scale-200.png b/test/TestApps/PushNotificationsDemoPackage/Images/SplashScreen.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..023e7f1feda78d5100569825acedfd213a0d84e9 GIT binary patch literal 7700 zcmeHLYj~4Yw%(;oxoEH#Kxq-eR|+VkP17b#Vk;?4QwkI+A{L04G+#<<(x#Un1#+h5>eArRq zTw$)ZvTWW_Y?bDho0nPVTh08+s`sp!j74rJTTtXIDww0SILedFv?sZ?yb@@}GN;#8 znk_b~Q(A0YR#uV4ef!osoV1M3;vQ8N$O|fStfgf$S5;ddUNv`tWtGjM;koG#N;7M< zP*84lnx(bn_KF&9Z5Ai$)#Cs3a|$OFw>WKCT$of*L7_CqQEinflT|W{JT+aKp-E0v zsxmYg)1(T>DROm+LN1eQw8}KCTp=C!$H7`PU!t9_Hw@TsTI2`udRZv*!a5`#A9hK6Y95L(CDUX&_@QxKV z_feX{UhA#ZWlvgpL$#w^D#lq`_A4AzDqd|Zv6y9PX&DNcN|l}_D^{q@GG&H^Pg583 z8FI6N8^H7b5WjGp;urW)d7F+_lcp%KsLX0viCmE(OHH+=%ZfD_=`voUuoUxFO^L;- z;!;2{g-YiiO6m4bs89OuF9!p{FGtH-f%8<2gY!h9s)4ciN%{Kh1+`}{^}M~+TDH9N z^Z5PlgVXMC&2&k*Hw^Lb9gny#ro$MOIxIt{+r)EA10$VR3 zanN8D{TUkl+v0CQ_>ZoHP<M-x#8@8ZiT#$Kh`(uRaX1g$Bg|qy$<#7 zSSAi{Nb8Y=lvNVeio+UGLCAtoLBfL`iOv`)yoJMDJBN>4IH@(l7YRF;61@>qq1iM9 zr@b#OC~SAxSle?5Pp8Z78{VO0YFr1x7kZU64Z23eLf2T2#6J_t;-E}DkB?NufZ0Ug zi?J&byXeaB-uTNVhuiM!UVQw}bZrJ3GtAETYp->!{q#zfN7D3AS9@Q7*V^85jGx#R z(QxYV(wW#F0XF9^^s>>H8pPlVJ>)3Oz z&_X8Sf@~?cH_O*cgi$U#`v`RRfv#y3m(ZpKk^5uLup+lVs$~}FZU$r_+}#hl%?g5m z-u-}-666ssp-xWQak~>PPy$mRc|~?pVSs1_@mBEXpPVfLF6(Ktf1S* zPPh@QZ=tFMs?LM2(5P3L2;l_6XX6s&cYsP1ip#eg0`ZEP0HGYh{UmS@o`MihLLvkU zgyAG0G`b1|qjxxh1(ODKFE%AP}Dq=3vK$P7TXP4GrM1kQ72!GUVMDl`rDC&2;TA}*nF z8$nQD&6ys_nc1*E7$*1S@R8$ymy(sQV}imGSedB@{!QR5P&N_H=-^o!?LsWs+2|mH z-e=)T^SvI)=_JIm7}j4;@*Z17=(#}m=~YF~z~CLI+vdAGlJDcdF$TM?CVI1%LhUrN zaa6DJ=Yh$)$k&Oz{-~8yw^GM^8prYxSxo zvI4k#ibryMa%%*8oI-5m61Koa_A_xg=(fwp0aBX{;X4Q;NXUhtaoJDo1>TqhWtn=_ zd5~chq#&6~c%8JZK#t_&J(9EVUU&upYeIovLt1>vaHe}UUq>#RGQj!EN#5+0@T`(@ z^g~>*c`VGRiSt;!$_4+0hk^I!@O3``5=sZ8IwlxWW7km1B&_t&E*u0_9UBa#VqwY* zz>nxv?FAsVnRaD(Bui=6i==BFUw0k4n$>`umU`F2l?7CYTD^)c2X+d9X&ddS9|gj? zM?knGkGCX&W8offw8aLC2$D{PjC3nVZwd4k?eZH8*mZ)U@3Qk8RDFOz_#WUA#vnzy zyP>KrCfKwSXea7}jgJjBc}PGY+4#6%lbZyjhy`5sZd_Vy6Wz;ixa?czkN}J9It1K6 zY!eu>|AwF^fwZlLAYyQI*lM@^>O>Iu6Vf6i>Q$?v!SeUS<{>UYMwz$*%Aq?w^`j{h z!$GZbhu=^D{&ET8;))LL%ZBDZkQqRd2;u~!d9bHGmLRhLDctNgYyjsuvoSZ#iVdoB z2!f--UUA#U;<{je#?cYt^{PIyKa%hW>}uepWMyAI{{Zo7?2>?$c9;whJae%oN|I-kpTQSx_C$Z&;f zi2i)qmEn=y4U0uvk)$m;zKfjPK@oc?I`}1Jzl$Q~aoKBd3kt7L#7gyt|A_qgz6ai< z=X%D1i!d2h?rHR^R8SUj&G||dkC?DT>{o#Yau<@uqVT{Xef&XG}5*E4aPk{}~ zplx&XhaV)&1EfI3Em;Bw#O5SV^c;{twb-1Rw)+=0!e_BLbd7tYmXCH0wrlOSS+~`7He8Iqx0{CN+DVit9;*6L~JAN zD&cyT)2?h}xnYmL?^)<7YyzZ3$FHU^Eg;DLqAV{#wv#Wj7S`Jdl1pX&{3(uZ?!uh} zDc$ZTNV*7le_W6}Hju~GMTxZQ1aWCeUc%!jv3MHAzt>Y-nQK%zfT*3ebDQA5b?iGn; zBjv3B+GhLTexd_(CzZDP4|#n5^~scvB6#Pk%Ho!kQ>yYw((Dv{6=$g3jT1!u6gORW zx5#`7Wy-ZHRa~IxGHdrp(bm%lf>2%J660nj$fCqN(epv@y!l9s7@k6EvxS{AMP>WY zX4$@F8^kayphIx-RGO$+LYl9YdoI5d|4#q9##`_F5Xnx`&GPzp2fB{-{P@ATw=X@~ z_|&^UMWAKD;jjBKTK(~o?cUFRK8EX=6>cXpfzg4ZpMB>*w_^8GSiT-Jp|xBOnzM+j z*09-@-~qJ(eqWq5@R4i^u4^{McCP(!3}C|v_WsTR*bIUxN(Nx`u##3B4{sE`Z`v8w zAwIG`?1~PkID~W{uDzmqH98Pew_1(;x2%8r^vY{)_&J2K)cN{W+h5+g)ZcjP&Ci#O zgy|8K@4kyMfwilHd&6TDlhb%++Pk!>9HRld6HT7gwyZGrxS$}CsD6`>6!!2K1@Mjf z(P0WYB7V_OFZyeWrbOFb>O54BNXf~K&?}3=^v;v_wT{DKr?jN^DtN&DXwX%u?s*c6`%8>WFz z7}YW^tp0bp^NriE)AB6M2l<7rn7fzePtR*omOevpfm9n?}2V*+0iW;S)C zhg`NAjL?D=W#k*$aR{>pGf~lD-rVtD;5jW1_*Jn1j1=es@Kcx4ySM_bwcQCT=d+DV z>Sz~L=Hj@(X%31nK$mWI@7d>}ORB`K(p=+`UD)+99YUGQc7y^bHZ1F(8|tL0 zdK*DT0kSXG_{BKTpP2*2PecdKV9;dq$^ZZDP;Nyq1kp-&GI5eAyZsK!e3V zK@rPy*{(`KIfo+lc878mDKk^V#`VT05}64kBtk%DgwLrOvLMj5-;*GNKv6c6pzMuL z6EP%ob|_0IW}lLRXCP2!9wWhEw3LA7iF#1O1mIZ@Z=6&bz41F;@S_GvYAG-#CW3z{ zP3+6vHhvP&A3$##Vo9$dT^#MoGg^|MDm=Bt1d2RRwSZ<;ZHICpLBv5Xs!D?BH^(9_ z7`H=N&^v|Z-%mP}wNzG{aiFCsRgwzwq!N6obW9+7(R; z(SZ=23`|`>qil!LMGG{_Heq!BD>(Y-zV9wD)}hz25JA37YR%39;kI4y9pgtcUass6 zP24}ZY$vvYeI`zy&)A_X#nY3017ap*0&jx|mVwyGhg3;!keU53a}Uhm3BZI$N$6Se zLWlAmy1S0xKJm4G_U@sN_Tm=`$xWJSEwKU98rZ&)1R^*$$1vA3oG#&*%SMxY_~oGP zP&PFJatFLM-Ps%84IV-+Ow)T{C7cqUAvauy4C z(FRz&?6$Rypj{xO!`y=*J5o4@U8Q-(y5(*=YoKeZ+-1YdljXxkA#B)zo=FeQH#?Le zycNUmEEHWO9a=X^pb#&cOq7-`7UA87#|S22)<7RUtZo|(zibX=w;K3qur9vy#`MNV z6UUcf9ZwEnKCCp+OoBnF@OdbvH)ANXO0o~Pi9l8=x3))}L<#vO0-~O4!~--Ket?d} zJaqsj<@CD1%S2cTW%rOP{Vto%0sGW~1RMa_j^)5nil0Yw- z0EE#bP+l4#P^%PQ+N*oxu1Zq05xZ!bXfYTg>9c{(Iw*lnjR^>kz%lAN^zFce7rppy zY8zA~3GD=A6d*hze&l4D_wA~+O!56)BZTe_rEu}Ezi<4!kG|W#amBZ5{&XS2@6R~H z{9o^y*BkH4$~yX9U&@CgbOzX1bn9xqF|zh$Dh0Y5y*E0e90*$!ObrHY3Ok0`2=O~r zCuke6KrP9KOf?V(YDsM<6pX2nVoN%M$LT^q#FmtaF?1^27F*IcNX~XRB(|hCFvdcc zc)$=S-)acdk$g4?_>jRqxpI6M3vHZk?0c^3=byamYDNf;uB{3NlKW5IhnOS3DNkMV z?tK8?kJ}pmvp%&&eTVOVjHP`q34hN1@!aK}H(K!vI`~gf|Gv+FNEQD5Yd<~yX7k_l h&G-K)@HZb3BABY{)U1?^%I#E6`MGoTtustd{~yM6srvu` literal 0 HcmV?d00001 diff --git a/test/TestApps/PushNotificationsDemoPackage/Images/Square150x150Logo.scale-200.png b/test/TestApps/PushNotificationsDemoPackage/Images/Square150x150Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..af49fec1a5484db1d52a7f9b5ec90a27c7030186 GIT binary patch literal 2937 zcma)84OCO-8BSud5)jwMLRVKgX(S?$n?Ld|vrsm<$CF7)&zTbyy1FE5bU`Q17MRv`9ue$;R(@8kR;#vJ*IM0>cJIAOte!d7oRgdH zd%ySjdB6L9=gX^A6)VzH7p2l@v~3zJAMw|DFy#^)F@@F*`mqUn=Il>l)8_+ab;nOW{%+iPx z+s{Eu|&pIs)Z7{La9~?xKfyl z#43?gjEL15d4WbOZo#SiP%>DB^+BcnJ=7dHEe;r#G=tuw|ka z%q@}##Uh7;tc%L_64m(kHtw74ty%BJMb)_1)#S0j`)F8_1jF7vScpsnH=0V19bO8y zR`0SjIdCUo&=>JwMQF8KHA<{ODHTiQh}0^@5QRmCA?gOH6_H3K^-_sNB^RrdNuK-R zOO*vOrKCVvDwgUck`kF(E7j{I#iiN;b*ZdCt4m@HPA`EuEqGGf4%!K<;(=I=&Vyrw z%TwcWtxa}8mCZ%Cyf&ActJ6_$ox5z6-D!0-dvnRx6t7y3d+h6QYpKWO;8OdnvERo7 zuEf>ih5`wqY)~o@OeVt-wM?Q!>QzdGRj!bz6fzYrfw$hZfAKzr2-M+D+R>}~oT574c;_3zquHcElqKIsryILt3g8n3jcMb+j?i?-L3FpZJ z2WRVBRdDPc+G5aaYg#5hpE+6nQ|(VSoxT3|biF;BUq#==-27Xi=gihDPYP$7?=9cP zYKE$jeQ|3~_L0VG-(F~2ZPyD0=k{J4Q~h(t__{-mz_w8{JDY9{`1ouzz!Vr5!ECdE z6U~O1k8c}24V7~zzXWTV-Pe4)y}wQJS&q%H5`Fo_f_JvIU489aCX$;P`u#!I-=^4ijC2{&9!O&h>mi?9oYD=GC#%)6{GzN6nQYw+Fal50!#x^asjBBR50i`+mho*ttoqV)ubM2KD9S~k7+FR4>{29?6 z{!l6kDdyTN0YJ9LgkPWeXm|gyi@zM3?0@{&pXT12w|78&W-q!RRF)&iLCEZVH<|fR zN0fr2^t8H(>L?>K#>^+jWROLral(Qy-xoBq1U7A&DV||wClb)Otd9?(gZ|8znMF}D zf<1haWz^s0qgecz;RFGt0C-B4g`jNGHsFU+;{<%t65v^sjk^h$lmWn#B0#_)9ij&d z-~lc`A)YYExi^7sBuPM^Y|wA2g*5?`K?#7tzELQYNxGo$UB$4J8RJp1k(8Jj+~hMT zlN~>M@KTTh^--8y3PK_NZ@AC!{PT=CziBzGd+wTJ^@icH!Bd}%)g8V)%K?|c&WTUk zy}qv1C%(fjRoZ4ozC3{O%@5?)XzH35zHns$pgU*Q?fj4v?fp1Qbm+j;3l;9jam9Da zXVcKjPlQ73x78QPu|Ffm6x?`~e3oD=gl=4kYK?={kD5j~QCXU)`HSdduNNENzA*2$ zOm3PzF!lN5e*06-f1Uot67wY#{o-S1!KZ7E=!~7ynnk9_iJR#kFoNbAOT#^2Gd17F zMmvU6>lndZQGd|ax9kUoXXO+$N?|j@6qpsF&_j7YXvwo_C{JpmLw5&#e6k>atv%es z5)7r*Wvv_JkUpT}M!_o!nVlEk1Zbl=a*2hQ*<|%*K1Glj^FcF`6kTzGQ3lz~2tCc@ z&x|tj;aH&1&9HwcJBcT`;{?a+pnej;M1HO(6Z{#J!cZA04hnFl;NXA+&`=7bjW_^o zfC40u3LMG?NdPtwGl>Tq6u}*QG)}-y;)lu-_>ee3kibW(69n0$0Zy!}9rQz%*v1iO zT9_H>99yIrSPYVy6^);rR}7Yo=J_T@hi+qhTZXnVWyf;JDYm5#eYLTxr*?kiNn!+Y zQ+LUkBafNJ#rH#C(?d5^;gw9o#%daEI{mA*LHPIHPU`#|H$hD zwm>0&+kahQ)E#%~k>&5@&#Vg82H?s%71=)(soi@174pi9--2{w{1$}Sz4zGn3Du&x bht0Iza^2ykEt4(epJ78uh5nDlX8(TxzDYwP literal 0 HcmV?d00001 diff --git a/test/TestApps/PushNotificationsDemoPackage/Images/Square44x44Logo.scale-200.png b/test/TestApps/PushNotificationsDemoPackage/Images/Square44x44Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..ce342a2ec8a61291ba76c54604aea7e9d20af11b GIT binary patch literal 1647 zcmaJ?eM}Q)7(e+G1Q(|`V9JhTI2>MkceK4;p;PR&$Pi?ejk3YQ_3o`S&|W_dsOZ8# zWPTt69g`t$ab`0cj-Y0yiBSOqmd)tG7G(}M5aP0_%&9TijB#&)I{zSE^4@#z^FF`l z`8{8`o%wlL(UI|y2!cdsuVamHH~H86F!*-15em4)NqUpCQM5?aoC_eCf@lV4wvF2a zjDQn1JBL69f&@2M3rvzJcfE!eZ8FZUBlFlC5RD)it33{mF9#B82AiyQE%w)`vlwa> zv{<1sm&kSKK$&%2jSFn7$t&P%%6Ue>R=EAnG8N7fqynWG8L3p!4801a;8{+nliO(qd(jNJ_?+9W3#hLIDLoT6~3fx9=`CC-D}-AMrpEO7HK zt3$GicGPc?GmDjy7K2P@La;eu4!$zWCZ`ym{Z$b zu-O6RM&K4JT|BIZB`E-gxqG%FzanI#+2FFmqHqXG7yxWB=w55RGOM)$xMb(>kSNR z2w=1AZi%z=AmG~yea~XaXJR!v7vLn(RUnELfiB1|6D84ICOS}^Zo2AdN}<&*h}G_u z{xZ!(%>tLT3J3<5XhWy-tg+6)0nmUUENLW8TWA{R6bgVd3X;anYFZ^IRis*_P-C-r z;i>%1^eL3UI2-{w8nuFFcs0e~7J{O2k^~Ce%+Ly4U?|=!0LH=t6()xi<^I-rs+9sF z*q{E-CxZbGPeu#a;XJwE;9S1?#R&uns>^0G3p`hEUF*v`M?@h%T%J%RChmD|EVydq zmHWh*_=S%emRC*mhxaVLzT@>Z2SX0u9v*DIJ@WC^kLVdlGV6LpK$KIrlJqc zpJ921)+3JJdTx|<`G&kXpKkjGJv=76R`yYIQ{#c-`%+`#V(7}Q;&@6U8!Td1`d;?N z_9mnI#?AA}4J!r)LN4!E-@H5eXauuB7TOawS>Y|{-P?NNx-lq+z1W-+y(;39P&&LP zL{N80?&=C*qKmdA^moMZRuPcD!B<*mq$ch=0Cnlitw#txRWhb3%TQvPqjkC`F69G4b! ze7z9MZ#+;_#l?H37UqUhDFb^l&s2{oM$3I0o^Q!yx;;V)QmCMo)Tb_ui|mit8MS?U zm##6$sZZ1$@|s%?l@>4Z<*Q}sRBSKMhb4I{e5LdEhsHIHTe8Bod5c>6QtT>$XgUBz z6MK`kO$=jmt@FqggOhJ5j~e@ygRbG;<{Vu)*+nn9aQeo0;$#j;|MS=S$&L?BeV25z xs3B`@=#`5TF{^6(A1rvdY@|-RtQ|iS5{tyX+wH?;n8E)G$kykv-D^wh{{!TZT%7;_ literal 0 HcmV?d00001 diff --git a/test/TestApps/PushNotificationsDemoPackage/Images/Square44x44Logo.targetsize-24_altform-unplated.png b/test/TestApps/PushNotificationsDemoPackage/Images/Square44x44Logo.targetsize-24_altform-unplated.png new file mode 100644 index 0000000000000000000000000000000000000000..f6c02ce97e0a802b85f6021e822c89f8bf57d5cd GIT binary patch literal 1255 zcmaJ>TWs4@7*5+{G#S+&C!qC#> zf>5N3P6jO*Cz>ug*(_DmW=)kea&m$gZ^+nyiF`;j%w@}y8)>p*SH}C`m?DXeieF2U zyQHecc_L%Gh!7GMt+hG06y;+|p4>m~}PjA}rKViGiEnn7G0ZO<>G|7q;2?NwGCM3s?eued6%hd$B+ z*kQJ{#~$S=DFE(%=E+UkmlEI*%3llUf~8Ja9YU1Vui0IbGBkW_gHB%Rd&!!ioX zs40O?i9I{};kle7GMvE7(rk`la=gTI)47=>%?q@^iL-nUo3}h4S}N-KHn8t5mVP8w z&bSErwp+37 zNJJ8?a|{r5Q3R0Z5s-LB1WHOwYC@7pCHWND#cL1cZ?{kJ368_*(UDWUDyb<}0y@o# zfMF016iMWPCb6obAxT$JlB6(2DrlXDTB&!0`!m??4F(qWMhjVZo?JXQmz`1*58Z=& zcDmB|S-E@j?BoFGix0flckqdS4jsPNzhfWyWIM98GxcLs89C(~dw%$_t;JjX-SD}E zfiGV;{8Q%8r}w9x>EEigW81>`kvnU@pK)4+xk9@+bNj9L!AAZ@SZ@q|)&BmY3+HZx zul~BeG4|}-;L%cHViQGQX?^zFfO0&#cHwel=d`lH9sJ-@Sl@n*(8J2>%Ac`IxyY?Q z{=GhWvC#gu-~Ia7*n{=+;qM?Ul_wy1+u7ho;=`>EwP^g~R@{unBds`!#@}tluZQpS zm)M~nYEifJWJGx?_6DcTy>#uh%>!H9=hb^(v`=m3F1{L>db=<5_tm+_&knAQ2EU$s Mu9UqpbNZeC0BbUo^Z)<= literal 0 HcmV?d00001 diff --git a/test/TestApps/PushNotificationsDemoPackage/Images/StoreLogo.png b/test/TestApps/PushNotificationsDemoPackage/Images/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..7385b56c0e4d3c6b0efe3324aa1194157d837826 GIT binary patch literal 1451 zcmaJ>eN5D57_Z|bH;{0+1#mbl)eTU3{h)Wf7EZV?;HD@XL@{B`Ui%(2aMxQ~xdXSv z5nzWi(LW)U2=Vc-cY@s7nPt{i0hc6!7xN4NNHI#EQl>YNBy8l4%x9gr_W-j zEZMQmmTIy(>;lblRfh`dIyTgc9W5d!VP$L4(kKrN1c5G~(O_#xG zAJCNTstD^5SeXFB+&$h=ToJP2H>xr$iqPs-#O*;4(!Fjw25-!gEb*)mU}=)J;Iu>w zxK(5XoD0wrPSKQ~rbL^Cw6O_03*l*}i=ydbu7adJ6y;%@tjFeXIXT+ms30pmbOP%Q zX}S;+LBh8Tea~TSkHzvX6$rYb)+n&{kSbIqh|c7hmlxmwSiq5iVhU#iEQ<>a18|O^Sln-8t&+t`*{qBWo5M?wFM(JuimAOb5!K#D}XbslM@#1ZVz_;!9U zpfEpLAOz=0g@bd6Xj_ILi-x^!M}73h^o@}hM$1jflTs|Yuj9AL@A3<-?MV4!^4q`e z)fO@A;{9K^?W?DbnesnPr6kK>$zaKo&;FhFd(GYFCIU^T+OIMb%Tqo+P%oq(IdX7S zf6+HLO?7o0m+p>~Tp5UrXWh!UH!wZ5kv!E`_w)PTpI(#Iw{AS`gH4^b(bm^ZCq^FZ zY9DD7bH}rq9mg88+KgA$Zp!iWncuU2n1AuIa@=sWvUR-s`Qb{R*kk(SPU^`$6BXz8 zn#7yaFOIK%qGxyi`dYtm#&qqox0$h=pNi#u=M8zUG@bpiZ=3sT=1}Trr}39cC)H|v zbL?W)=&s4zrh)7>L(|cc%$1#!zfL?HjpeP%T+x_a+jZ16b^iKOHxFEX$7d|8${H-* zIrOJ5w&i$>*D>AKaIoYg`;{L@jM((Kt?$N$5OnuPqVvq**Nm}(f0wwOF%iX_Pba;V z;m@wxX&NcV3?<1+u?A{y_DIj7#m3Af1rCE)o`D&Y3}0%7E;iX1yMDiS)sh0wKi!36 zL!Wmq?P^Ku&rK~HJd97KkLTRl>ScGFYZNlYytWnhmuu|)L&ND8_PmkayQb{HOY640 bno1(wj@u8DCVuFR|31B*4ek@pZJqxCDDe1x literal 0 HcmV?d00001 diff --git a/test/TestApps/PushNotificationsDemoPackage/Images/Wide310x150Logo.scale-200.png b/test/TestApps/PushNotificationsDemoPackage/Images/Wide310x150Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..288995b397fdbef1fb7e85afd71445d5de1952c5 GIT binary patch literal 3204 zcmbVPeQXow8NYmBd90>}0NP?GhXW~VaeThm=a0tV#EwJMI!)6M3}|c4_Bl3=Kd>G0 z(GHx1wl<7(tP?FsOQkTilSo*iIvF%uArExJ73~P zSv1xEy!U(Wd4A9D`FQV@W3@F^qJ@PEF$@z`Z!*BbFsS(^?B zyiAzJ+q})bkgiQHWqEb*jJD-coHYr1^iocg)l!Qa{Xqs-l~6J}p-|##ZHYofskQ3$ zI0;xzXyhazBeXhIsg5A=%ufo@f)1yy&ScKS0;HF^!r_2UE^lpZEom(+@duma3awTv zCrCL-%D_SvYWIcdHkmI}#50(fkUi)Qgx!80ju>g1za^}ff>JI8Z@^-iCiaCgg@TgF z+vtE?Q9{VQUX&MW9SYYmGcxA14%N2@7FwBTD4N<(2{nWgV8$e3?-F=L^&FrtWn~(U_Q~~^uYiyeY6-KoTnfh9AWz@ zIKje0)u!_Lw)E}G!#kEfwKVdNt(UAf9*f>tEL_(=xco-T%jTi@7YlC3hs2ik%Le0H ztj}RTeCF(5mwvi3_56>-yB?l;J>-1%!9~=fs|QcNG3J~a@JCu`4SB460s0ZO+##4fFUSGLcj_ja^fL4&BKALfb#$6$O?>P@qx2Agl^x0i&ugt zsy5Pyu=()`7HRMG3IB7F1@`_ z+-!J%#i6e^U$e#+C%Q>_qVRzWRsG^W_n+@OcX@vzI&z;mzHNb!GQ?LWA(wtpqHqTM z1OFw_{Zn?fD)p)`c`kOgv{de=v@suGRqY{N^U7gI1VF3*F=obwaXI6ob5__Yn zVTguS!%(NI09J8x#AO_aW!9W7k*UvB;IWDFC3srwftr{kHj%g)fvnAm;&h_dnl~

MY- zf+K}sCe8qU6Ujs`3ua{U0Of$R_gVQBuUA za0v=mu#vIOqiiAZOr&h*$WyOw&k-xr$;G4Ixa!#TJNr>95(h>l%)PUy4p+^SgR(uR zta%k*?ny-+nAr8spEk1fo{J4i!b^Fia`N{_F6@zidA2ZTTrjl#^5Z-2KfB@Cu}l9s z(*|Z2jc?p~vn2f)3y9i*7zJV1L{$?|&q)4oaT;uXi6>1GkRXVTOzAz(RHEmr=eFIi z`}<>-Q?K0GN8!IYxeP1XKXO+jsJbp~o^);Bc;%b7Flpe7;1`Ny@3r7ZR;?R)aJt8C ziNlEC<@3f_lIV4TwV}&e;D!Ee5_|e#g0LUh=5vmYWYm7&2h*M>QPKvGh9-)wfMMW3 z8J9b%1k7dzPzO0_NGQy92BZ^FR6R~6;^6?lqO;-QUP4BY%cG%3vEhbm#>4vIhPBh3 z-+pZGjh$x%Hp{?=FHsMp0&wNPlj00us{&`1ZOZTqs8%4X&xH=UDr*xyBW(Zp&Em94 zf)ZSfn#yg0N)>!1kWdkqJ^S*z0FF5|fj&qcE#Na|%OY0$uO>!&hP+1ywfD_WXk@4J(?MBftK7>$Nvqh@tDuarN%PrTLQ2Uzysx>UV=V zk^RrDSvdQ?0;=hY67EgII-f4`t=+i*yS=Y~!XlqIy_4x&%+OdfbKOFPXS2X5%4R{N z$SQMX^AK6(fA + + + + + + + MSIXPackager + purifoypaul + Images\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + ReunionTestProtocol + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/TestApps/PushNotificationsDemoPackage/PushNotificationsDemoPackage.wapproj b/test/TestApps/PushNotificationsDemoPackage/PushNotificationsDemoPackage.wapproj new file mode 100644 index 0000000000..075e8cea2e --- /dev/null +++ b/test/TestApps/PushNotificationsDemoPackage/PushNotificationsDemoPackage.wapproj @@ -0,0 +1,121 @@ + + + + 15.0 + + + + Debug + x86 + + + Release + x86 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM + + + Release + ARM + + + Debug + ARM64 + + + Release + ARM64 + + + Debug + AnyCPU + + + Release + AnyCPU + + + + $(MSBuildExtensionsPath)\Microsoft\DesktopBridge\ + + + + 424a6d96-37ee-4456-8347-08ab425c8dbe + 10.0.19041.0 + 10.0.17763.0 + en-US + True + ..\PushNotificationsDemoApp\PushNotificationsDemoApp.vcxproj + 1E9C85490A5DCF9AC7E2E56B6DBFF5C703761922 + True + SHA256 + False + C:\Users\purifoypaul\Desktop\Work\ProjectReunionReset\ProjectReunion\BuildOutput\Release\x64\ + True + x64 + C:\Users\purifoypaul\Desktop\Work\ProjectReunionReset\ProjectReunion\BuildOutput\Debug\x64\PushNotificationDemoPackages + 0 + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + + Designer + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From c22476e8f06357d9372f083f71bbeae74c520ca9 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Fri, 14 May 2021 14:07:58 -0700 Subject: [PATCH 02/53] Fixed AppLifecycle packager build files --- .../AppLifecycleTestPackage/AppLifecycleTestPackage.wapproj | 3 +-- test/TestApps/AppLifecycleTestPackage/Package.appxmanifest | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/test/TestApps/AppLifecycleTestPackage/AppLifecycleTestPackage.wapproj b/test/TestApps/AppLifecycleTestPackage/AppLifecycleTestPackage.wapproj index af6d65c595..4c5732991e 100644 --- a/test/TestApps/AppLifecycleTestPackage/AppLifecycleTestPackage.wapproj +++ b/test/TestApps/AppLifecycleTestPackage/AppLifecycleTestPackage.wapproj @@ -58,12 +58,12 @@ ..\AppLifecycleTestApp\AppLifecycleTestApp.vcxproj true False + $(SolutionDir)temp\MSTest.pfx SHA256 True True $(Platform) 0 - 3A5485ABFA9FA31CC7DD1907102213D1ED1A0292 Always @@ -101,7 +101,6 @@ - diff --git a/test/TestApps/AppLifecycleTestPackage/Package.appxmanifest b/test/TestApps/AppLifecycleTestPackage/Package.appxmanifest index 75ef8059fc..1cf84af436 100644 --- a/test/TestApps/AppLifecycleTestPackage/Package.appxmanifest +++ b/test/TestApps/AppLifecycleTestPackage/Package.appxmanifest @@ -8,8 +8,8 @@ + Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" + Version="1.0.0.0" /> AppLifecycleTestPackage @@ -59,4 +59,4 @@ - + \ No newline at end of file From f87a4e7ee7f46a3a84627187fd0be35f97c67629 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Thu, 13 May 2021 14:05:47 -0700 Subject: [PATCH 03/53] Push Notifications Components --- .../AppLifecycleTestPackage/AppLifecycleTestPackage.wapproj | 3 ++- test/TestApps/AppLifecycleTestPackage/Package.appxmanifest | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/test/TestApps/AppLifecycleTestPackage/AppLifecycleTestPackage.wapproj b/test/TestApps/AppLifecycleTestPackage/AppLifecycleTestPackage.wapproj index 4c5732991e..af6d65c595 100644 --- a/test/TestApps/AppLifecycleTestPackage/AppLifecycleTestPackage.wapproj +++ b/test/TestApps/AppLifecycleTestPackage/AppLifecycleTestPackage.wapproj @@ -58,12 +58,12 @@ ..\AppLifecycleTestApp\AppLifecycleTestApp.vcxproj true False - $(SolutionDir)temp\MSTest.pfx SHA256 True True $(Platform) 0 + 3A5485ABFA9FA31CC7DD1907102213D1ED1A0292 Always @@ -101,6 +101,7 @@ + diff --git a/test/TestApps/AppLifecycleTestPackage/Package.appxmanifest b/test/TestApps/AppLifecycleTestPackage/Package.appxmanifest index 1cf84af436..a6ec91e3a1 100644 --- a/test/TestApps/AppLifecycleTestPackage/Package.appxmanifest +++ b/test/TestApps/AppLifecycleTestPackage/Package.appxmanifest @@ -8,8 +8,8 @@ + Publisher="CN=WNP_Reunion" + Version="1.0.2.0" /> AppLifecycleTestPackage From 978de5e77b571b1076f78461e550e5e512fc9925 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Fri, 14 May 2021 14:21:51 -0700 Subject: [PATCH 04/53] Revert AppLifecycle build files --- .../AppLifecycleTestPackage/AppLifecycleTestPackage.wapproj | 3 +-- test/TestApps/AppLifecycleTestPackage/Package.appxmanifest | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/test/TestApps/AppLifecycleTestPackage/AppLifecycleTestPackage.wapproj b/test/TestApps/AppLifecycleTestPackage/AppLifecycleTestPackage.wapproj index af6d65c595..4c5732991e 100644 --- a/test/TestApps/AppLifecycleTestPackage/AppLifecycleTestPackage.wapproj +++ b/test/TestApps/AppLifecycleTestPackage/AppLifecycleTestPackage.wapproj @@ -58,12 +58,12 @@ ..\AppLifecycleTestApp\AppLifecycleTestApp.vcxproj true False + $(SolutionDir)temp\MSTest.pfx SHA256 True True $(Platform) 0 - 3A5485ABFA9FA31CC7DD1907102213D1ED1A0292 Always @@ -101,7 +101,6 @@ - diff --git a/test/TestApps/AppLifecycleTestPackage/Package.appxmanifest b/test/TestApps/AppLifecycleTestPackage/Package.appxmanifest index a6ec91e3a1..1cf84af436 100644 --- a/test/TestApps/AppLifecycleTestPackage/Package.appxmanifest +++ b/test/TestApps/AppLifecycleTestPackage/Package.appxmanifest @@ -8,8 +8,8 @@ + Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" + Version="1.0.0.0" /> AppLifecycleTestPackage From ba38c1be91644617310dfb0afbaa02af74d86ff6 Mon Sep 17 00:00:00 2001 From: Paul Purifoy <33183370+pmpurifoy@users.noreply.github.com> Date: Fri, 14 May 2021 14:34:19 -0700 Subject: [PATCH 05/53] [Draft] Add PushNotifications unit tests (#821) * Add unittests * Added Background activation tests * Quick Clean up * Fixed Activator tests * Address comments for channel request unittests * Addressed PR comments for activation * Close channel after every test pass * Added build updates * Update Package.appxmanifest * Update Package.appxmanifest Co-authored-by: Sharath Manchala <10109130+sharath2727@users.noreply.github.com> --- ProjectReunion.sln | 104 +++++ .../PushNotificationManager.cpp | 2 +- test/PushNotificationTests/APITests.cpp | 175 ++++++++ .../MockBackgroundTaskInstance.cpp | 54 +++ .../MockBackgroundTaskInstance.h | 30 ++ .../MockRawNotification.cpp | 24 + .../MockRawNotification.h | 27 ++ .../PushNotificationTests.vcxproj | 198 ++++++++ .../PushNotificationTests.vcxproj.filters | 51 +++ test/PushNotificationTests/Shared.cpp | 155 +++++++ test/PushNotificationTests/Shared.h | 21 + test/PushNotificationTests/packages.config | 6 + test/PushNotificationTests/pch.cpp | 5 + test/PushNotificationTests/pch.h | 36 ++ .../PushNotificationsDemoApp.vcxproj | 8 +- .../Package.appxmanifest | 2 +- .../PushNotificationsDemoPackage.wapproj | 15 +- .../PushNotificationsTestApp.vcxproj | 178 ++++++++ .../PushNotificationsTestApp.vcxproj.filters | 33 ++ .../PushNotificationsTestApp/main.cpp | 423 ++++++++++++++++++ .../PushNotificationsTestApp/packages.config | 5 + .../TestApps/PushNotificationsTestApp/pch.cpp | 3 + test/TestApps/PushNotificationsTestApp/pch.h | 16 + .../Images/LockScreenLogo.scale-200.png | Bin 0 -> 1430 bytes .../Images/SplashScreen.scale-200.png | Bin 0 -> 7700 bytes .../Images/Square150x150Logo.scale-200.png | Bin 0 -> 2937 bytes .../Images/Square44x44Logo.scale-200.png | Bin 0 -> 1647 bytes ...x44Logo.targetsize-24_altform-unplated.png | Bin 0 -> 1255 bytes .../Images/StoreLogo.png | Bin 0 -> 1451 bytes .../Images/Wide310x150Logo.scale-200.png | Bin 0 -> 3204 bytes .../Package.appxmanifest | 65 +++ .../PushNotificationsTestAppPackage.wapproj | 117 +++++ test/inc/TestDef.h | 3 + 33 files changed, 1740 insertions(+), 16 deletions(-) create mode 100644 test/PushNotificationTests/APITests.cpp create mode 100644 test/PushNotificationTests/MockBackgroundTaskInstance.cpp create mode 100644 test/PushNotificationTests/MockBackgroundTaskInstance.h create mode 100644 test/PushNotificationTests/MockRawNotification.cpp create mode 100644 test/PushNotificationTests/MockRawNotification.h create mode 100644 test/PushNotificationTests/PushNotificationTests.vcxproj create mode 100644 test/PushNotificationTests/PushNotificationTests.vcxproj.filters create mode 100644 test/PushNotificationTests/Shared.cpp create mode 100644 test/PushNotificationTests/Shared.h create mode 100644 test/PushNotificationTests/packages.config create mode 100644 test/PushNotificationTests/pch.cpp create mode 100644 test/PushNotificationTests/pch.h create mode 100644 test/TestApps/PushNotificationsTestApp/PushNotificationsTestApp.vcxproj create mode 100644 test/TestApps/PushNotificationsTestApp/PushNotificationsTestApp.vcxproj.filters create mode 100644 test/TestApps/PushNotificationsTestApp/main.cpp create mode 100644 test/TestApps/PushNotificationsTestApp/packages.config create mode 100644 test/TestApps/PushNotificationsTestApp/pch.cpp create mode 100644 test/TestApps/PushNotificationsTestApp/pch.h create mode 100644 test/TestApps/PushNotificationsTestAppPackage/Images/LockScreenLogo.scale-200.png create mode 100644 test/TestApps/PushNotificationsTestAppPackage/Images/SplashScreen.scale-200.png create mode 100644 test/TestApps/PushNotificationsTestAppPackage/Images/Square150x150Logo.scale-200.png create mode 100644 test/TestApps/PushNotificationsTestAppPackage/Images/Square44x44Logo.scale-200.png create mode 100644 test/TestApps/PushNotificationsTestAppPackage/Images/Square44x44Logo.targetsize-24_altform-unplated.png create mode 100644 test/TestApps/PushNotificationsTestAppPackage/Images/StoreLogo.png create mode 100644 test/TestApps/PushNotificationsTestAppPackage/Images/Wide310x150Logo.scale-200.png create mode 100644 test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest create mode 100644 test/TestApps/PushNotificationsTestAppPackage/PushNotificationsTestAppPackage.wapproj diff --git a/ProjectReunion.sln b/ProjectReunion.sln index c1632e21b7..6ef32ecf93 100644 --- a/ProjectReunion.sln +++ b/ProjectReunion.sln @@ -128,10 +128,18 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PushNotificationsDemoApp", EndProject Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "PushNotificationsDemoPackage", "test\TestApps\PushNotificationsDemoPackage\PushNotificationsDemoPackage.wapproj", "{424A6D96-37EE-4456-8347-08AB425C8DBE}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PushNotificationsTestApp", "test\TestApps\PushNotificationsTestApp\PushNotificationsTestApp.vcxproj", "{56A1D696-FEDA-4333-BF37-772EBECECB10}" +EndProject +Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "PushNotificationsTestAppPackage", "test\TestApps\PushNotificationsTestAppPackage\PushNotificationsTestAppPackage.wapproj", "{D012E4BB-F16B-472D-A26D-D449CEFA988E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PushNotificationTests", "test\PushNotificationTests\PushNotificationTests.vcxproj", "{0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution + test\inc\inc.vcxitems*{0a5fee93-48b7-40ec-bb9a-b27d11060da9}*SharedItemsImports = 4 dev\PushNotifications\PushNotifications.vcxitems*{103c0c23-7ba8-4d44-a63c-83488e2e3a81}*SharedItemsImports = 9 dev\UndockedRegFreeWinRT\UndockedRegFreeWinRT.vcxitems*{56371ca6-144b-4989-a4e9-391ad4fa7651}*SharedItemsImports = 9 + test\inc\inc.vcxitems*{56a1d696-feda-4333-bf37-772ebececb10}*SharedItemsImports = 4 test\inc\inc.vcxitems*{7c502995-59c3-483b-86ba-815985353633}*SharedItemsImports = 4 test\inc\inc.vcxitems*{8e52d7ea-a200-4a6b-ba74-8efb49468caf}*SharedItemsImports = 4 test\inc\inc.vcxitems*{b567fe2e-3a03-48d0-b2b5-760cdec35891}*SharedItemsImports = 9 @@ -513,6 +521,99 @@ Global {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|x86.ActiveCfg = Release|x86 {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|x86.Build.0 = Release|x86 {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|x86.Deploy.0 = Release|x86 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|Any CPU.ActiveCfg = Debug|Win32 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|Any CPU.Build.0 = Debug|Win32 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|ARM.ActiveCfg = Debug|Win32 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|ARM.Build.0 = Debug|Win32 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|ARM64.ActiveCfg = Debug|Win32 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|ARM64.Build.0 = Debug|Win32 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|x64.ActiveCfg = Debug|x64 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|x64.Build.0 = Debug|x64 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|x86.ActiveCfg = Debug|Win32 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|x86.Build.0 = Debug|Win32 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|ARM.ActiveCfg = Debug|Win32 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|ARM64.ActiveCfg = Debug|Win32 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|x64.ActiveCfg = Debug|x64 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|x64.Build.0 = Debug|x64 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|x86.ActiveCfg = Debug|Win32 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|x86.Build.0 = Debug|Win32 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|Any CPU.ActiveCfg = Release|Win32 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|ARM.ActiveCfg = Release|Win32 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|ARM64.ActiveCfg = Release|Win32 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|x64.ActiveCfg = Release|x64 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|x64.Build.0 = Release|x64 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|x86.ActiveCfg = Release|Win32 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|x86.Build.0 = Release|Win32 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|Any CPU.ActiveCfg = Debug|Any CPU + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|Any CPU.Build.0 = Debug|Any CPU + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|Any CPU.Deploy.0 = Debug|Any CPU + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|ARM.ActiveCfg = Debug|ARM + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|ARM.Build.0 = Debug|ARM + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|ARM.Deploy.0 = Debug|ARM + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|ARM64.Build.0 = Debug|ARM64 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|ARM64.Deploy.0 = Debug|ARM64 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|x64.ActiveCfg = Debug|x64 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|x64.Build.0 = Debug|x64 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|x64.Deploy.0 = Debug|x64 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|x86.ActiveCfg = Debug|x86 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|x86.Build.0 = Debug|x86 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|x86.Deploy.0 = Debug|x86 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|ARM.ActiveCfg = Debug|ARM + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|ARM.Build.0 = Debug|ARM + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|ARM.Deploy.0 = Debug|ARM + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|ARM64.Build.0 = Debug|ARM64 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|x64.ActiveCfg = Debug|x64 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|x64.Build.0 = Debug|x64 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|x64.Deploy.0 = Debug|x64 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|x86.ActiveCfg = Debug|x86 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|x86.Build.0 = Debug|x86 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|x86.Deploy.0 = Debug|x86 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|Any CPU.Build.0 = Release|Any CPU + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|Any CPU.Deploy.0 = Release|Any CPU + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|ARM.ActiveCfg = Release|ARM + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|ARM.Build.0 = Release|ARM + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|ARM.Deploy.0 = Release|ARM + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|ARM64.ActiveCfg = Release|ARM64 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|ARM64.Build.0 = Release|ARM64 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|ARM64.Deploy.0 = Release|ARM64 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|x64.ActiveCfg = Release|x64 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|x64.Build.0 = Release|x64 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|x64.Deploy.0 = Release|x64 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|x86.ActiveCfg = Release|x86 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|x86.Build.0 = Release|x86 + {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|x86.Deploy.0 = Release|x86 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|Any CPU.ActiveCfg = Debug|Win32 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|Any CPU.Build.0 = Debug|Win32 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|ARM.ActiveCfg = Debug|Win32 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|ARM.Build.0 = Debug|Win32 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|ARM64.ActiveCfg = Debug|Win32 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|ARM64.Build.0 = Debug|Win32 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|x64.ActiveCfg = Debug|x64 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|x64.Build.0 = Debug|x64 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|x86.ActiveCfg = Debug|Win32 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|x86.Build.0 = Debug|Win32 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|ARM.ActiveCfg = Debug|Win32 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|ARM64.ActiveCfg = Debug|Win32 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|x64.ActiveCfg = Debug|x64 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|x64.Build.0 = Debug|x64 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|x86.ActiveCfg = Debug|Win32 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|x86.Build.0 = Debug|Win32 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|Any CPU.ActiveCfg = Release|Win32 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|ARM.ActiveCfg = Release|Win32 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|ARM64.ActiveCfg = Release|Win32 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|x64.ActiveCfg = Release|x64 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|x64.Build.0 = Release|x64 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|x86.ActiveCfg = Release|Win32 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -556,6 +657,9 @@ Global {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} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4B3D7591-CFEC-4762-9A07-ABE99938FB77} diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp index 824e147918..132eb1faba 100644 --- a/dev/PushNotifications/PushNotificationManager.cpp +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -63,7 +63,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation return false; } - THROW_IF_FAILED(packagedProcessHResult); + THROW_IF_WIN32_ERROR(packagedProcessHResult); return true; } diff --git a/test/PushNotificationTests/APITests.cpp b/test/PushNotificationTests/APITests.cpp new file mode 100644 index 0000000000..a76544d058 --- /dev/null +++ b/test/PushNotificationTests/APITests.cpp @@ -0,0 +1,175 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#include "pch.h" +#include +#include "Shared.h" +#include "MockBackgroundTaskInstance.h" + +using namespace WEX::Common; +using namespace WEX::Logging; +using namespace WEX::TestExecution; + +using namespace winrt::Windows::ApplicationModel::Activation; +using namespace winrt::Windows::ApplicationModel::Background; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Foundation::Collections; +using namespace winrt::Windows::Management::Deployment; +using namespace winrt::Windows::Storage; +using namespace winrt::Windows::System; + + +// TODO: Write Register/Unregister tests that utilize the Assoc APIs to validate results. + +namespace Test::PushNotifications +{ + class APITests + { + private: + wil::unique_event m_failed; + + const std::wstring c_testPackageFile = g_deploymentDir + L"PushNotificationsTestAppPackage.msixbundle"; + const std::wstring c_testPackageCertFile = g_deploymentDir + L"PushNotificationsTestAppPackage.cer"; + const std::wstring c_testPackageFullName = L"PushNotificationsTestAppPackage_1.0.0.0_x64__8wekyb3d8bbwe"; + + public: + BEGIN_TEST_CLASS(APITests) + TEST_CLASS_PROPERTY(L"Description", L"Project Reunion Push Notifications test") + TEST_CLASS_PROPERTY(L"IsolationLevel", L"Method") + TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA") + TEST_CLASS_PROPERTY(L"RunFixtureAs:Class", L"ElevatedUser") + END_TEST_CLASS() + + TEST_CLASS_SETUP(ClassInit) + { + TP::AddPackage_ProjectReunionFramework(); + try + { + RunCertUtil(c_testPackageCertFile, false); + InstallPackage(c_testPackageFile); + } + catch (...) + { + return false; + } + return true; + } + + TEST_CLASS_CLEANUP(ClassUninit) + { + TP::RemovePackage_ProjectReunionFramework(); + + try + { + UninstallPackage(c_testPackageFullName); + RunCertUtil(c_testPackageCertFile, true); + } + catch (...) + { + return false; + } + return true; + } + + TEST_METHOD_SETUP(MethodInit) + { + VERIFY_IS_TRUE(TP::IsPackageRegistered_ProjectReunionFramework()); + + m_failed = CreateTestEvent(c_testFailureEventName); + + return true; + } + + TEST_METHOD_CLEANUP(MethodUninit) + { + VERIFY_IS_TRUE(TP::IsPackageRegistered_ProjectReunionFramework()); + + return true; + } + + TEST_METHOD(ChannelRequestUsingNullRemoteId) + { + wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); + + // This is associated protocol for the MSIX installed app for launch. + // Use the ://path to define the component you want to test. + Uri launchUri{ c_testProtocolScheme_Packaged + L"://ChannelRequestUsingNullRemoteId" }; + auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); + VERIFY_IS_TRUE(launchResult); + + WaitForEvent(event, m_failed); + } + + TEST_METHOD(ChannelRequestUsingRemoteId) + { + wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); + + // This is associated protocol for the MSIX installed app for launch. + // Use the ://path to define the component you want to test. + Uri launchUri{ c_testProtocolScheme_Packaged + L"://ChannelRequestUsingRemoteId" }; + auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); + VERIFY_IS_TRUE(launchResult); + + WaitForEvent(event, m_failed); + } + + TEST_METHOD(MultipleChannelRequestUsingSameRemoteId) + { + wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); + + // This is associated protocol for the MSIX installed app for launch. + // Use the ://path to define the component you want to test. + Uri launchUri{ c_testProtocolScheme_Packaged + L"://MultipleChannelRequestUsingSameRemoteId" }; + auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); + VERIFY_IS_TRUE(launchResult); + + WaitForEvent(event, m_failed); + } + + TEST_METHOD(MultipleChannelRequestUsingMultipleRemoteId) + { + wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); + + // This is associated protocol for the MSIX installed app for launch. + // Use the ://path to define the component you want to test. + Uri launchUri{ c_testProtocolScheme_Packaged + L"://MultipleChannelRequestUsingMultipleRemoteId" }; + auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); + VERIFY_IS_TRUE(launchResult); + + WaitForEvent(event, m_failed); + } + + TEST_METHOD(ThreeChannelRequestUsingSameRemoteId) + { + wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); + + // This is associated protocol for the MSIX installed app for launch. + // Use the ://path to define the component you want to test. + Uri launchUri{ c_testProtocolScheme_Packaged + L"://ThreeChannelRequestUsingSameRemoteId" }; + auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); + VERIFY_IS_TRUE(launchResult); + + WaitForEvent(event, m_failed); + } + + TEST_METHOD(BackgroundActivation) + { + wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); + auto LocalBackgroundTask = winrt::create_instance(c_comServerId, CLSCTX_ALL); + auto mockBackgroundTaskInstance = winrt::make(); + LocalBackgroundTask.Run(mockBackgroundTaskInstance); + WaitForEvent(event, m_failed); + } + + TEST_METHOD(ActivatorTest) + { + wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); + Uri launchUri{ c_testProtocolScheme_Packaged + L"://ActivatorTest" }; + auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); + VERIFY_IS_TRUE(launchResult); + + WaitForEvent(event, m_failed); + } + + }; +} diff --git a/test/PushNotificationTests/MockBackgroundTaskInstance.cpp b/test/PushNotificationTests/MockBackgroundTaskInstance.cpp new file mode 100644 index 0000000000..055134a109 --- /dev/null +++ b/test/PushNotificationTests/MockBackgroundTaskInstance.cpp @@ -0,0 +1,54 @@ +#pragma once + +#include "pch.h" +#include "MockBackgroundTaskInstance.h" +#include "MockRawNotification.h" +#include + +using namespace winrt::Windows::Networking::PushNotifications; + +winrt::guid MockBackgroundTaskInstance::InstanceId() +{ + return winrt::guid(); +} + +UINT32 MockBackgroundTaskInstance::SuspendedCount() +{ + return 0; +} + +UINT32 MockBackgroundTaskInstance::Progress() +{ + return 0; +} + +UINT32 MockBackgroundTaskInstance::Progress(UINT32 progress) +{ + return 0; +} + +winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration MockBackgroundTaskInstance::Task() +{ + return nullptr; +} + +winrt::event_token MockBackgroundTaskInstance::Canceled(winrt::Windows::ApplicationModel::Background::BackgroundTaskCanceledEventHandler const& handler) +{ + return winrt::event_token{}; +} + +void MockBackgroundTaskInstance::Canceled(winrt::event_token const& token) noexcept +{ + return; +} + +winrt::Windows::ApplicationModel::Background::BackgroundTaskDeferral MockBackgroundTaskInstance::GetDeferral() +{ + return nullptr; +} + +winrt::Windows::Foundation::IInspectable MockBackgroundTaskInstance::TriggerDetails() +{ + auto rawNotification = winrt::make(); + return rawNotification; +} diff --git a/test/PushNotificationTests/MockBackgroundTaskInstance.h b/test/PushNotificationTests/MockBackgroundTaskInstance.h new file mode 100644 index 0000000000..35f0fe2813 --- /dev/null +++ b/test/PushNotificationTests/MockBackgroundTaskInstance.h @@ -0,0 +1,30 @@ +#include + +struct MockBackgroundTaskInstance : winrt::implements +{ + MockBackgroundTaskInstance() {}; + + winrt::guid InstanceId(); + UINT32 SuspendedCount(); + UINT32 Progress(); + UINT32 Progress(UINT32 progress); + winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration Task(); + winrt::Windows::Foundation::IInspectable TriggerDetails(); + winrt::event_token Canceled(winrt::Windows::ApplicationModel::Background::BackgroundTaskCanceledEventHandler const& handler); + void Canceled(winrt::event_token const& token) noexcept; + winrt::Windows::ApplicationModel::Background::BackgroundTaskDeferral GetDeferral(); +}; + +struct MockBackgroundTaskInstanceFactory : 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/test/PushNotificationTests/MockRawNotification.cpp b/test/PushNotificationTests/MockRawNotification.cpp new file mode 100644 index 0000000000..465c115279 --- /dev/null +++ b/test/PushNotificationTests/MockRawNotification.cpp @@ -0,0 +1,24 @@ +#include "pch.h" +#include "MockRawNotification.h" + +winrt::Windows::Foundation::Collections::IMapView MockRawNotification::Headers() +{ + return winrt::Windows::Foundation::Collections::IMapView{}; +} + +winrt::hstring MockRawNotification::ChannelId() +{ + return winrt::hstring(L"SampleChannelId"); +} + +winrt::hstring MockRawNotification::Content() +{ + return winrt::hstring(c_rawNotificationPayload); +} + +winrt::Windows::Storage::Streams::IBuffer MockRawNotification::ContentBytes() +{ + winrt::Windows::Storage::Streams::DataWriter dataWriter{}; + dataWriter.WriteString(c_rawNotificationPayload); + return dataWriter.DetachBuffer(); +} diff --git a/test/PushNotificationTests/MockRawNotification.h b/test/PushNotificationTests/MockRawNotification.h new file mode 100644 index 0000000000..f55b6f5951 --- /dev/null +++ b/test/PushNotificationTests/MockRawNotification.h @@ -0,0 +1,27 @@ +#include +#include +#include + +struct MockRawNotification : winrt::implements +{ + MockRawNotification() {}; + + winrt::Windows::Foundation::Collections::IMapView Headers(); + winrt::hstring ChannelId(); + winrt::hstring Content(); + winrt::Windows::Storage::Streams::IBuffer ContentBytes(); +}; + +struct MockRawNotificationFactory : 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/test/PushNotificationTests/PushNotificationTests.vcxproj b/test/PushNotificationTests/PushNotificationTests.vcxproj new file mode 100644 index 0000000000..b00566483d --- /dev/null +++ b/test/PushNotificationTests/PushNotificationTests.vcxproj @@ -0,0 +1,198 @@ + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {0a5fee93-48b7-40ec-bb9a-b27d11060da9} + PushNotificationTests + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;PUSHNOTIFICATIONTESTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + + + + Level3 + true + true + true + WIN32;NDEBUG;PUSHNOTIFICATIONTESTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + + + + + Level3 + true + _DEBUG;PUSHNOTIFICATIONTESTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + + + + Level3 + true + true + true + NDEBUG;PUSHNOTIFICATIONTESTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + _Debug + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + \ No newline at end of file diff --git a/test/PushNotificationTests/PushNotificationTests.vcxproj.filters b/test/PushNotificationTests/PushNotificationTests.vcxproj.filters new file mode 100644 index 0000000000..e98f8d727d --- /dev/null +++ b/test/PushNotificationTests/PushNotificationTests.vcxproj.filters @@ -0,0 +1,51 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Source Files + + + Source Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + + \ No newline at end of file diff --git a/test/PushNotificationTests/Shared.cpp b/test/PushNotificationTests/Shared.cpp new file mode 100644 index 0000000000..28e2ae08cb --- /dev/null +++ b/test/PushNotificationTests/Shared.cpp @@ -0,0 +1,155 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. +#include +#include +#include "Shared.h" + +using namespace WEX::Common; +using namespace WEX::Logging; +using namespace WEX::TestExecution; + +using namespace winrt; +using namespace winrt::Windows::ApplicationModel; +using namespace winrt::Windows::ApplicationModel::Activation; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Foundation::Collections; +using namespace winrt::Windows::Management::Deployment; +using namespace winrt::Windows::Storage; +using namespace winrt::Windows::System; + +namespace Test::PushNotifications +{ + StorageFile CreateDocFile(std::wstring filename) + { + return KnownFolders::DocumentsLibrary().CreateFileAsync(filename, + CreationCollisionOption::OpenIfExists).get(); + } + + StorageFile OpenDocFile(std::wstring filename) + { + return KnownFolders::DocumentsLibrary().GetFileAsync(filename).get(); + } + + wil::unique_handle Execute(const std::wstring& command, const std::wstring& args, + const std::wstring& directory) + { + SHELLEXECUTEINFO ei{}; + ei.cbSize = sizeof(SHELLEXECUTEINFO); + ei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_DOENVSUBST; + ei.lpFile = command.c_str(); + ei.lpParameters = args.c_str(); + ei.lpDirectory = directory.c_str(); + + if (!ShellExecuteEx(&ei)) + { + auto lastError = GetLastError(); + VERIFY_WIN32_SUCCEEDED(lastError); + } + + wil::unique_handle process{ ei.hProcess }; + return process; + } + + void RunCertUtil(const std::wstring& path, bool removeCert) + { + std::wstring action = (removeCert ? L"-delstore" : L"-addstore"); + std::wstring args{ action + L" TrustedPeople " + path }; + // VERIFY_ARE_NOT_EQUAL(args, args); + auto process = Execute(L"%SystemRoot%\\system32\\certutil.exe", + args.c_str(), g_deploymentDir); + + // Wait for the cer to be installed. + auto waitResult = WaitForSingleObject(process.get(), c_phaseTimeout); + if (waitResult != WAIT_OBJECT_0) + { + auto lastError = GetLastError(); + VERIFY_WIN32_FAILED(lastError); + } + + // Make sure the exitcode for the tool is success. + DWORD exitCode{}; + THROW_IF_WIN32_BOOL_FALSE(GetExitCodeProcess(process.get(), &exitCode)); + VERIFY_ARE_EQUAL(exitCode, 0); + } + + void InstallPackage(const std::wstring& packagePath) + { + // Deploy packaged app to register handler through the manifest. + PackageManager manager; + IVector depPackagePaths; + auto result = manager.AddPackageAsync(Uri(packagePath), depPackagePaths, + DeploymentOptions::ForceApplicationShutdown).get(); + auto errorText = result.ErrorText(); + auto errorCode = result.ExtendedErrorCode(); + VERIFY_SUCCEEDED(errorCode, errorText.c_str()); + } + + void UninstallPackage(const std::wstring& packageFullName) + { + // Deploy packaged app to register handler through the manifest. + PackageManager manager; + IVector depPackagePaths; + auto result = manager.RemovePackageAsync(packageFullName).get(); + auto errorText = result.ErrorText(); + auto errorCode = result.ExtendedErrorCode(); + VERIFY_SUCCEEDED(errorCode, errorText.c_str()); + } + + wil::unique_event CreateTestEvent(const std::wstring& eventName) + { + bool alreadyExists = false; + SECURITY_ATTRIBUTES attributes = {}; + wil::unique_hlocal_security_descriptor descriptor; + + // Grant access to world and appcontainer. + THROW_IF_WIN32_BOOL_FALSE(ConvertStringSecurityDescriptorToSecurityDescriptor( + L"D:(A;;GA;;;WD)(A;;GA;;;AC)", SDDL_REVISION_1, &descriptor, nullptr)); + attributes.nLength = sizeof(SECURITY_ATTRIBUTES); + attributes.lpSecurityDescriptor = descriptor.get(); + + wil::unique_event event; + event.create(wil::EventOptions::None, eventName.c_str(), &attributes, &alreadyExists); + return event; + } + + void WaitForEvent(const wil::unique_event& successEvent, const wil::unique_event& failedEvent) + { + HANDLE waitEvents[2] = { successEvent.get(), failedEvent.get() }; + auto waitResult = WaitForMultipleObjects(_countof(waitEvents), waitEvents, FALSE, + c_phaseTimeout); + + // If waitResult == failureEventIndex, it means the remote test process signaled a + // failure event while we were waiting for a different event. + auto failureEventIndex = WAIT_OBJECT_0 + 1; + VERIFY_ARE_NOT_EQUAL(waitResult, failureEventIndex); + + VERIFY_ARE_NOT_EQUAL(waitResult, WAIT_TIMEOUT); + if (waitResult == WAIT_FAILED) + { + auto lastError = GetLastError(); + VERIFY_WIN32_FAILED(lastError); + } + + successEvent.ResetEvent(); + failedEvent.ResetEvent(); + } + + const std::wstring GetDeploymentDir() + { + WEX::Common::String testDeploymentDir; + WEX::TestExecution::RuntimeParameters::TryGetValue(L"TestDeploymentDir", testDeploymentDir); + return reinterpret_cast(testDeploymentDir.GetBuffer()); + } + + void WriteContentFile(std::wstring filename) + { + auto file = CreateDocFile(filename); + FileIO::WriteTextAsync(file, L"Hello, World!").get(); + } + + void DeleteContentFile(std::wstring filename) + { + auto file = CreateDocFile(filename); + file.DeleteAsync().get(); + } +} diff --git a/test/PushNotificationTests/Shared.h b/test/PushNotificationTests/Shared.h new file mode 100644 index 0000000000..5128b67ab1 --- /dev/null +++ b/test/PushNotificationTests/Shared.h @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. +#pragma once + +namespace Test::PushNotifications +{ + winrt::Windows::Storage::StorageFile CreateDocFile(std::wstring filename); + winrt::Windows::Storage::StorageFile OpenDocFile(std::wstring filename); + wil::unique_handle Execute(const std::wstring& command, const std::wstring& args, + const std::wstring& directory); + void RunCertUtil(const std::wstring& path, bool removeCert = false); + void InstallPackage(const std::wstring& packagePath); + void UninstallPackage(const std::wstring& packageFullName); + wil::unique_event CreateTestEvent(const std::wstring& eventName); + void WaitForEvent(const wil::unique_event& successEvent, const wil::unique_event& failedEvent); + const std::wstring GetDeploymentDir(); + void WriteContentFile(std::wstring filename); + void DeleteContentFile(std::wstring filename); + + const std::wstring g_deploymentDir = GetDeploymentDir(); +} diff --git a/test/PushNotificationTests/packages.config b/test/PushNotificationTests/packages.config new file mode 100644 index 0000000000..d756bde0e3 --- /dev/null +++ b/test/PushNotificationTests/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/test/PushNotificationTests/pch.cpp b/test/PushNotificationTests/pch.cpp new file mode 100644 index 0000000000..64b7eef6d6 --- /dev/null +++ b/test/PushNotificationTests/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: source file corresponding to the pre-compiled header + +#include "pch.h" + +// When you are using pre-compiled headers, this source file is necessary for compilation to succeed. diff --git a/test/PushNotificationTests/pch.h b/test/PushNotificationTests/pch.h new file mode 100644 index 0000000000..7c2becaf82 --- /dev/null +++ b/test/PushNotificationTests/pch.h @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#ifndef PCH_H +#define PCH_H +#endif //PCH_H + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +namespace TP = ::Test::Packages; diff --git a/test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj b/test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj index 620823cb70..5cf53ecdd5 100644 --- a/test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj +++ b/test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj @@ -151,14 +151,14 @@ - ..\..\..\BuildOutput\Release\x64\ProjectReunion_DLL\Microsoft.Windows.AppLifecycle.winmd + $(OutDir)\..\ProjectReunion_DLL\Microsoft.Windows.AppLifecycle.winmd true - Microsoft.ProjectReunion.dll + $(OutDir)\..\ProjectReunion_DLL\Microsoft.ProjectReunion.dll - ..\..\..\BuildOutput\Release\x64\ProjectReunion_DLL\Microsoft.Windows.PushNotifications.winmd + $(OutDir)\..\ProjectReunion_DLL\Microsoft.Windows.PushNotifications.winmd true - Microsoft.ProjectReunion.dll + $(OutDir)\..\ProjectReunion_DLL\Microsoft.ProjectReunion.dll diff --git a/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest b/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest index bb30e5d988..0f6f091160 100644 --- a/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest +++ b/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest @@ -9,7 +9,7 @@ diff --git a/test/TestApps/PushNotificationsDemoPackage/PushNotificationsDemoPackage.wapproj b/test/TestApps/PushNotificationsDemoPackage/PushNotificationsDemoPackage.wapproj index 075e8cea2e..ce21dd0476 100644 --- a/test/TestApps/PushNotificationsDemoPackage/PushNotificationsDemoPackage.wapproj +++ b/test/TestApps/PushNotificationsDemoPackage/PushNotificationsDemoPackage.wapproj @@ -56,14 +56,13 @@ en-US True ..\PushNotificationsDemoApp\PushNotificationsDemoApp.vcxproj - 1E9C85490A5DCF9AC7E2E56B6DBFF5C703761922 - True + true + False + $(SolutionDir)temp\MSTest.pfx SHA256 - False - C:\Users\purifoypaul\Desktop\Work\ProjectReunionReset\ProjectReunion\BuildOutput\Release\x64\ + True True - x64 - C:\Users\purifoypaul\Desktop\Work\ProjectReunionReset\ProjectReunion\BuildOutput\Debug\x64\PushNotificationDemoPackages + $(Platform) 0 @@ -109,13 +108,9 @@ - - - - \ No newline at end of file diff --git a/test/TestApps/PushNotificationsTestApp/PushNotificationsTestApp.vcxproj b/test/TestApps/PushNotificationsTestApp/PushNotificationsTestApp.vcxproj new file mode 100644 index 0000000000..d4601f457f --- /dev/null +++ b/test/TestApps/PushNotificationsTestApp/PushNotificationsTestApp.vcxproj @@ -0,0 +1,178 @@ + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + $(OutDir)\..\ProjectReunion_DLL\Microsoft.Windows.AppLifecycle.winmd + true + $(OutDir)\..\ProjectReunion_DLL\Microsoft.ProjectReunion.dll + + + $(OutDir)\..\ProjectReunion_DLL\Microsoft.Windows.PushNotifications.winmd + true + $(OutDir)\..\ProjectReunion_DLL\Microsoft.ProjectReunion.dll + + + + 16.0 + Win32Proj + {56a1d696-feda-4333-bf37-772ebececb10} + PushNotificationsTestApp + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file diff --git a/test/TestApps/PushNotificationsTestApp/PushNotificationsTestApp.vcxproj.filters b/test/TestApps/PushNotificationsTestApp/PushNotificationsTestApp.vcxproj.filters new file mode 100644 index 0000000000..628b51e4d6 --- /dev/null +++ b/test/TestApps/PushNotificationsTestApp/PushNotificationsTestApp.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + + + Header Files + + + + + + \ No newline at end of file diff --git a/test/TestApps/PushNotificationsTestApp/main.cpp b/test/TestApps/PushNotificationsTestApp/main.cpp new file mode 100644 index 0000000000..f3d9cf75d0 --- /dev/null +++ b/test/TestApps/PushNotificationsTestApp/main.cpp @@ -0,0 +1,423 @@ +#include "pch.h" +#include +#include +#include +#include +#include // we need this for BackgroundTask APIs +using namespace winrt::Microsoft::Windows::AppLifecycle; +using namespace winrt::Microsoft::Windows::PushNotifications; +using namespace winrt; +using namespace winrt::Windows::Storage; +using namespace winrt::Windows::Storage::Streams; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::ApplicationModel::Activation; +using namespace winrt::Windows::ApplicationModel::Background; // BackgroundTask APIs + +enum UnitTest { + channelRequestUsingNullRemoteId, channelRequestUsingRemoteId, multipleChannelRequestUsingSameRemoteId, + multipleChannelRequestUsingMultipleRemoteId, threeChannelRequestUsingSameRemoteId, activatorTest, +}; + +static std::map switchMapping; +winrt::guid remoteId1(L"a2e4a323-b518-4799-9e80-0b37aeb0d225"); +winrt::guid remoteId2(L"CA1A4AB2-AC1D-4EFC-A132-E5A191CA285A"); +winrt::guid remoteId3(L"40FCE789-C6BF-4F47-A6CF-6B9C1DCE31BA"); + +void signalPhase(const std::wstring& phaseEventName) +{ + wil::unique_event phaseEvent; + if (phaseEvent.try_open(phaseEventName.c_str(), EVENT_MODIFY_STATE, false)) + { + phaseEvent.SetEvent(); + } +} + +void initUnitTestMapping() +{ + switchMapping["ChannelRequestUsingNullRemoteId"] = UnitTest::channelRequestUsingNullRemoteId; + switchMapping["ChannelRequestUsingRemoteId"] = UnitTest::channelRequestUsingRemoteId; + switchMapping["MultipleChannelRequestUsingSameRemoteId"] = UnitTest::multipleChannelRequestUsingSameRemoteId; + switchMapping["MultipleChannelRequestUsingMultipleRemoteId"] = UnitTest::multipleChannelRequestUsingMultipleRemoteId; + switchMapping["ThreeChannelRequestUsingSameRemoteId"] = UnitTest::threeChannelRequestUsingSameRemoteId; + switchMapping["ActivatorTest"] = UnitTest::activatorTest; +} + +bool ChannelRequestUsingNullRemoteId() +{ + winrt::hresult hr = S_OK; + + try + { + auto channelOperation = PushNotificationManager::CreateChannelAsync(GUID_NULL).get(); + } + catch (...) + { + auto channelRequestException = hresult_error(to_hresult()); + hr = channelRequestException.code(); + } + + return (hr == E_INVALIDARG); +} + +bool ChannelRequestUsingRemoteId() +{ + wil::unique_handle channelEvent = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + auto channelOperationResult = S_OK; + auto channelOperation = PushNotificationManager::CreateChannelAsync(remoteId1); + + // Setup the completed event handler + channelOperation.Completed( + [&channelEvent, &channelOperationResult]( + IAsyncOperationWithProgress const& sender, + AsyncStatus const /* asyncStatus */) + { + auto result = sender.GetResults(); + if (result.Status() == PushNotificationChannelStatus::CompletedSuccess) + { + result.Channel().Close(); // Avoids using cached channel everytime the test runs + } + else if (result.Status() == PushNotificationChannelStatus::CompletedFailure) + { + channelOperationResult = result.ExtendedError(); + } + + SetEvent(channelEvent.get()); + }); + + // The maximum amount of time it takes for channel request to be obtained - 16mins + if (WAIT_OBJECT_0 != WaitForSingleObject(channelEvent.get(), 960000 /* milliseconds */)) + { + channelOperation.Cancel(); + channelOperationResult = ERROR_TIMEOUT; + } + else + { + channelOperation.Close(); // Do not call getresults after this + } + + return (channelOperationResult == S_OK); +} + +bool MultipleChannelRequestUsingSameRemoteId() +{ + wil::unique_handle channelEvent1 = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + wil::unique_handle channelEvent2 = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + + auto channelOperationResult2 = S_OK; + + auto channelOperation1 = PushNotificationManager::CreateChannelAsync(remoteId1); + + channelOperation1.Completed( + [&channelEvent1]( + IAsyncOperationWithProgress const& sender, + AsyncStatus const /* asyncStatus */) + { + auto result = sender.GetResults(); + if (result.Status() == PushNotificationChannelStatus::CompletedSuccess) + { + result.Channel().Close(); // Avoids using cached channel everytime the test runs + } + else if (result.Status() == PushNotificationChannelStatus::CompletedFailure) + { + } + + SetEvent(channelEvent1.get()); + }); + + auto channelOperation2 = PushNotificationManager::CreateChannelAsync(remoteId1); + + channelOperation2.Completed( + [&channelEvent2, &channelOperationResult2]( + IAsyncOperationWithProgress const& sender, + AsyncStatus const /* asyncStatus */) + { + auto result = sender.GetResults(); + if (result.Status() == PushNotificationChannelStatus::CompletedSuccess) + { + result.Channel().Close(); // Avoids using cached channel everytime the test runs + } + else if (result.Status() == PushNotificationChannelStatus::CompletedFailure) + { + channelOperationResult2 = result.ExtendedError(); + } + + SetEvent(channelEvent2.get()); + }); + + // The maximum amount of time it takes for channel request to be obtained - 16mins + if (WAIT_OBJECT_0 != WaitForSingleObject(channelEvent2.get(), 960000 /* milliseconds */)) + { + channelOperation2.Cancel(); + channelOperationResult2 = ERROR_TIMEOUT; + } + + // The maximum amount of time it takes for channel request to be obtained - 16mins + if (WAIT_OBJECT_0 != WaitForSingleObject(channelEvent1.get(), 960000 /* milliseconds */)) + { + channelOperation1.Cancel(); + } + + return (channelOperationResult2 == WPN_E_OUTSTANDING_CHANNEL_REQUEST); +} + +bool MultipleChannelRequestUsingMultipleRemoteId() +{ + wil::unique_handle channelEvent1 = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + wil::unique_handle channelEvent2 = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + + auto channelOperationResult2 = S_OK; + + auto channelOperation1 = PushNotificationManager::CreateChannelAsync(remoteId1); + + channelOperation1.Completed( + [&channelEvent1]( + IAsyncOperationWithProgress const& sender, + AsyncStatus const /* asyncStatus */) + { + auto result = sender.GetResults(); + if (result.Status() == PushNotificationChannelStatus::CompletedSuccess) + { + result.Channel().Close(); + } + else if (result.Status() == PushNotificationChannelStatus::CompletedFailure) + { + } + + SetEvent(channelEvent1.get()); + }); + + auto channelOperation2 = PushNotificationManager::CreateChannelAsync(remoteId2); + + channelOperation2.Completed( + [&channelEvent2, &channelOperationResult2]( + IAsyncOperationWithProgress const& sender, + AsyncStatus const /* asyncStatus */) + { + auto result = sender.GetResults(); + if (result.Status() == PushNotificationChannelStatus::CompletedSuccess) + { + result.Channel().Close(); + } + else if (result.Status() == PushNotificationChannelStatus::CompletedFailure) + { + channelOperationResult2 = result.ExtendedError(); + } + + SetEvent(channelEvent2.get()); + }); + + // The maximum amount of time it takes for channel request to be obtained - 16mins + if (WAIT_OBJECT_0 != WaitForSingleObject(channelEvent2.get(), 960000 /* milliseconds */)) + { + channelOperation2.Cancel(); + channelOperationResult2 = ERROR_TIMEOUT; + } + + // The maximum amount of time it takes for channel request to be obtained - 16mins + if (WAIT_OBJECT_0 != WaitForSingleObject(channelEvent1.get(), 960000 /* milliseconds */)) + { + channelOperation1.Cancel(); + } + + return (channelOperationResult2 == WPN_E_OUTSTANDING_CHANNEL_REQUEST); +} + +bool ThreeChannelRequestUsingSameRemoteId() +{ + wil::unique_handle channelEvent1 = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + + wil::unique_handle channelEvent2 = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + auto channelOperationResult2 = S_OK; + + wil::unique_handle channelEvent3 = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + auto channelOperationResult3 = S_OK; + + auto channelOperation1 = PushNotificationManager::CreateChannelAsync(remoteId1); + + channelOperation1.Completed( + [&channelEvent1]( + IAsyncOperationWithProgress const& sender, + AsyncStatus const /* asyncStatus */) + { + auto result = sender.GetResults(); + if (result.Status() == PushNotificationChannelStatus::CompletedSuccess) + { + result.Channel().Close(); + } + else if (result.Status() == PushNotificationChannelStatus::CompletedFailure) + { + } + + SetEvent(channelEvent1.get()); + }); + + auto channelOperation2 = PushNotificationManager::CreateChannelAsync(remoteId2); + + channelOperation2.Completed( + [&channelEvent2, &channelOperationResult2]( + IAsyncOperationWithProgress const& sender, + AsyncStatus const /* asyncStatus */) + { + auto result = sender.GetResults(); + if (result.Status() == PushNotificationChannelStatus::CompletedSuccess) + { + result.Channel().Close(); + } + else if (result.Status() == PushNotificationChannelStatus::CompletedFailure) + { + channelOperationResult2 = result.ExtendedError(); + } + + SetEvent(channelEvent2.get()); + }); + + + auto channelOperation3 = PushNotificationManager::CreateChannelAsync(remoteId3); + + channelOperation3.Completed( + [&channelEvent3, &channelOperationResult3]( + IAsyncOperationWithProgress const& sender, + AsyncStatus const /* asyncStatus */) + { + auto result = sender.GetResults(); + if (result.Status() == PushNotificationChannelStatus::CompletedSuccess) + { + result.Channel().Close(); + } + else if (result.Status() == PushNotificationChannelStatus::CompletedFailure) + { + channelOperationResult3 = result.ExtendedError(); + } + + SetEvent(channelEvent3.get()); + }); + + // The maximum amount of time it takes for channel request to be obtained - 16mins + if (WAIT_OBJECT_0 != WaitForSingleObject(channelEvent2.get(), 960000 /* milliseconds */)) + { + channelOperation2.Cancel(); + channelOperationResult2 = ERROR_TIMEOUT; + } + + // The maximum amount of time it takes for channel request to be obtained - 16mins + if (WAIT_OBJECT_0 != WaitForSingleObject(channelEvent3.get(), 960000 /* milliseconds */)) + { + channelOperation3.Cancel(); + channelOperationResult3 = ERROR_TIMEOUT; + } + + // The maximum amount of time it takes for channel request to be obtained - 16mins + if (WAIT_OBJECT_0 != WaitForSingleObject(channelEvent1.get(), 960000 /* milliseconds */)) + { + channelOperation1.Cancel(); + } + + return ((channelOperationResult2 == WPN_E_OUTSTANDING_CHANNEL_REQUEST) && (channelOperationResult3 == WPN_E_OUTSTANDING_CHANNEL_REQUEST)); +} + +bool ActivatorTest() +{ + try + { + PushNotificationActivationInfo info( + PushNotificationRegistrationKind::PushTrigger | PushNotificationRegistrationKind::ComActivator, + c_fakeComServerId); + + auto token = PushNotificationManager::RegisterActivator(info); + if (!token.TaskRegistration()) + { + return false; + } + + PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationKind::PushTrigger | PushNotificationRegistrationKind::ComActivator); + } + catch (...) + { + return false; + } + return true; +} + +bool runUnitTest(std::string unitTest) +{ + switch (switchMapping[unitTest]) + { + case UnitTest::channelRequestUsingNullRemoteId: + return ChannelRequestUsingNullRemoteId(); + + case UnitTest::channelRequestUsingRemoteId: + return ChannelRequestUsingRemoteId(); + + case UnitTest::multipleChannelRequestUsingSameRemoteId: + return MultipleChannelRequestUsingSameRemoteId(); + + case UnitTest::multipleChannelRequestUsingMultipleRemoteId: + return MultipleChannelRequestUsingMultipleRemoteId(); + + case UnitTest::threeChannelRequestUsingSameRemoteId: + return ThreeChannelRequestUsingSameRemoteId(); + + case UnitTest::activatorTest: + return ActivatorTest(); + + default: + return false; + } +} + +int main() +{ + initUnitTestMapping(); + + PushNotificationActivationInfo info( + PushNotificationRegistrationKind::PushTrigger | PushNotificationRegistrationKind::ComActivator, + winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2")); // same clsid as app manifest + + auto token = PushNotificationManager::RegisterActivator(info); + + auto args = AppInstance::GetCurrent().GetActivatedEventArgs(); + auto kind = args.Kind(); + + if (kind == ExtendedActivationKind::Protocol) + { + auto protocolArgs = args.Data().as(); + Uri actualUri = protocolArgs.Uri(); + std::string unitTest = winrt::to_string(actualUri.Host()); + + std::cout << unitTest << std::endl; + + PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationKind::PushTrigger | PushNotificationRegistrationKind::ComActivator); + + // Switch on this variable to run specific components (uri://ComponentToTest) + auto output = runUnitTest(unitTest); + + if (output) + { + // Signal TAEF that protocol was activated and valid. + signalPhase(c_testProtocolScheme_Packaged); + } + else + { + // Signal TAEF that the test failed + signalPhase(c_testFailureEventName); + } + } + else if (kind == ExtendedActivationKind::Push) + { + PushNotificationReceivedEventArgs pushArgs = args.Data().as(); + auto payload = pushArgs.Payload(); + std::wstring payloadString(payload.begin(), payload.end()); + PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationKind::PushTrigger | PushNotificationRegistrationKind::ComActivator); + if (!payloadString.compare(c_rawNotificationPayload)) + { + signalPhase(c_testProtocolScheme_Packaged); + } + else + { + // Signal TAEF that the test failed + signalPhase(c_testFailureEventName); + } + } + + return 0; +}; diff --git a/test/TestApps/PushNotificationsTestApp/packages.config b/test/TestApps/PushNotificationsTestApp/packages.config new file mode 100644 index 0000000000..e8543f44a9 --- /dev/null +++ b/test/TestApps/PushNotificationsTestApp/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/test/TestApps/PushNotificationsTestApp/pch.cpp b/test/TestApps/PushNotificationsTestApp/pch.cpp new file mode 100644 index 0000000000..1a6cb122e2 --- /dev/null +++ b/test/TestApps/PushNotificationsTestApp/pch.cpp @@ -0,0 +1,3 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. +#include "pch.h" diff --git a/test/TestApps/PushNotificationsTestApp/pch.h b/test/TestApps/PushNotificationsTestApp/pch.h new file mode 100644 index 0000000000..e72c7ef953 --- /dev/null +++ b/test/TestApps/PushNotificationsTestApp/pch.h @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/test/TestApps/PushNotificationsTestAppPackage/Images/LockScreenLogo.scale-200.png b/test/TestApps/PushNotificationsTestAppPackage/Images/LockScreenLogo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..735f57adb5dfc01886d137b4e493d7e97cf13af3 GIT binary patch literal 1430 zcmaJ>TTC2P7~aKltDttVHYH6u8Io4i*}3fO&d$gd*bA_<3j~&e7%8(eXJLfhS!M@! zKrliY>>6yT4+Kr95$!DoD(Qn-5TP|{V_KS`k~E6(LGS@#`v$hQo&^^BKsw3HIsZBT z_y6C2n`lK@apunKojRQ^(_P}Mgewt$(^BBKCTZ;*xa?J3wQ7~@S0lUvbcLeq1Bg4o zH-bvQi|wt~L7q$~a-gDFP!{&TQfc3fX*6=uHv* zT&1&U(-)L%Xp^djI2?~eBF2cxC@YOP$+9d?P&h?lPy-9M2UT9fg5jKm1t$m#iWE{M zIf%q9@;fyT?0UP>tcw-bLkz;s2LlKl2qeP0w zECS7Ate+Awk|KQ+DOk;fl}Xsy4o^CY=pwq%QAAKKl628_yNPsK>?A>%D8fQG6IgdJ ztnxttBz#NI_a@fk7SU`WtrpsfZsNs9^0(2a z@C3#YO3>k~w7?2hipBf{#b6`}Xw1hlG$yi?;1dDs7k~xDAw@jiI*+tc;t2Lflg&bM)0!Y;0_@=w%`LW^8DsYpS#-bLOklX9r?Ei}TScw|4DbpW%+7 zFgAI)f51s}{y-eWb|vrU-Ya!GuYKP)J7z#*V_k^Xo>4!1Yqj*m)x&0L^tg3GJbVAJ zJ-Pl$R=NAabouV=^z_t;^K*0AvFs!vYU>_<|I^#c?>>CR<(T?=%{;U=aI*SbZADLH z&(f2wz_Y0??Tf|g;?|1Znw6}6U43Q#qNRwv1vp9uFn1)V#*4p&%$mP9x&15^OaBiDS(XppT|z^>;B{PLVEbS3IFYV yGvCsSX*m literal 0 HcmV?d00001 diff --git a/test/TestApps/PushNotificationsTestAppPackage/Images/SplashScreen.scale-200.png b/test/TestApps/PushNotificationsTestAppPackage/Images/SplashScreen.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..023e7f1feda78d5100569825acedfd213a0d84e9 GIT binary patch literal 7700 zcmeHLYj~4Yw%(;oxoEH#Kxq-eR|+VkP17b#Vk;?4QwkI+A{L04G+#<<(x#Un1#+h5>eArRq zTw$)ZvTWW_Y?bDho0nPVTh08+s`sp!j74rJTTtXIDww0SILedFv?sZ?yb@@}GN;#8 znk_b~Q(A0YR#uV4ef!osoV1M3;vQ8N$O|fStfgf$S5;ddUNv`tWtGjM;koG#N;7M< zP*84lnx(bn_KF&9Z5Ai$)#Cs3a|$OFw>WKCT$of*L7_CqQEinflT|W{JT+aKp-E0v zsxmYg)1(T>DROm+LN1eQw8}KCTp=C!$H7`PU!t9_Hw@TsTI2`udRZv*!a5`#A9hK6Y95L(CDUX&_@QxKV z_feX{UhA#ZWlvgpL$#w^D#lq`_A4AzDqd|Zv6y9PX&DNcN|l}_D^{q@GG&H^Pg583 z8FI6N8^H7b5WjGp;urW)d7F+_lcp%KsLX0viCmE(OHH+=%ZfD_=`voUuoUxFO^L;- z;!;2{g-YiiO6m4bs89OuF9!p{FGtH-f%8<2gY!h9s)4ciN%{Kh1+`}{^}M~+TDH9N z^Z5PlgVXMC&2&k*Hw^Lb9gny#ro$MOIxIt{+r)EA10$VR3 zanN8D{TUkl+v0CQ_>ZoHP<M-x#8@8ZiT#$Kh`(uRaX1g$Bg|qy$<#7 zSSAi{Nb8Y=lvNVeio+UGLCAtoLBfL`iOv`)yoJMDJBN>4IH@(l7YRF;61@>qq1iM9 zr@b#OC~SAxSle?5Pp8Z78{VO0YFr1x7kZU64Z23eLf2T2#6J_t;-E}DkB?NufZ0Ug zi?J&byXeaB-uTNVhuiM!UVQw}bZrJ3GtAETYp->!{q#zfN7D3AS9@Q7*V^85jGx#R z(QxYV(wW#F0XF9^^s>>H8pPlVJ>)3Oz z&_X8Sf@~?cH_O*cgi$U#`v`RRfv#y3m(ZpKk^5uLup+lVs$~}FZU$r_+}#hl%?g5m z-u-}-666ssp-xWQak~>PPy$mRc|~?pVSs1_@mBEXpPVfLF6(Ktf1S* zPPh@QZ=tFMs?LM2(5P3L2;l_6XX6s&cYsP1ip#eg0`ZEP0HGYh{UmS@o`MihLLvkU zgyAG0G`b1|qjxxh1(ODKFE%AP}Dq=3vK$P7TXP4GrM1kQ72!GUVMDl`rDC&2;TA}*nF z8$nQD&6ys_nc1*E7$*1S@R8$ymy(sQV}imGSedB@{!QR5P&N_H=-^o!?LsWs+2|mH z-e=)T^SvI)=_JIm7}j4;@*Z17=(#}m=~YF~z~CLI+vdAGlJDcdF$TM?CVI1%LhUrN zaa6DJ=Yh$)$k&Oz{-~8yw^GM^8prYxSxo zvI4k#ibryMa%%*8oI-5m61Koa_A_xg=(fwp0aBX{;X4Q;NXUhtaoJDo1>TqhWtn=_ zd5~chq#&6~c%8JZK#t_&J(9EVUU&upYeIovLt1>vaHe}UUq>#RGQj!EN#5+0@T`(@ z^g~>*c`VGRiSt;!$_4+0hk^I!@O3``5=sZ8IwlxWW7km1B&_t&E*u0_9UBa#VqwY* zz>nxv?FAsVnRaD(Bui=6i==BFUw0k4n$>`umU`F2l?7CYTD^)c2X+d9X&ddS9|gj? zM?knGkGCX&W8offw8aLC2$D{PjC3nVZwd4k?eZH8*mZ)U@3Qk8RDFOz_#WUA#vnzy zyP>KrCfKwSXea7}jgJjBc}PGY+4#6%lbZyjhy`5sZd_Vy6Wz;ixa?czkN}J9It1K6 zY!eu>|AwF^fwZlLAYyQI*lM@^>O>Iu6Vf6i>Q$?v!SeUS<{>UYMwz$*%Aq?w^`j{h z!$GZbhu=^D{&ET8;))LL%ZBDZkQqRd2;u~!d9bHGmLRhLDctNgYyjsuvoSZ#iVdoB z2!f--UUA#U;<{je#?cYt^{PIyKa%hW>}uepWMyAI{{Zo7?2>?$c9;whJae%oN|I-kpTQSx_C$Z&;f zi2i)qmEn=y4U0uvk)$m;zKfjPK@oc?I`}1Jzl$Q~aoKBd3kt7L#7gyt|A_qgz6ai< z=X%D1i!d2h?rHR^R8SUj&G||dkC?DT>{o#Yau<@uqVT{Xef&XG}5*E4aPk{}~ zplx&XhaV)&1EfI3Em;Bw#O5SV^c;{twb-1Rw)+=0!e_BLbd7tYmXCH0wrlOSS+~`7He8Iqx0{CN+DVit9;*6L~JAN zD&cyT)2?h}xnYmL?^)<7YyzZ3$FHU^Eg;DLqAV{#wv#Wj7S`Jdl1pX&{3(uZ?!uh} zDc$ZTNV*7le_W6}Hju~GMTxZQ1aWCeUc%!jv3MHAzt>Y-nQK%zfT*3ebDQA5b?iGn; zBjv3B+GhLTexd_(CzZDP4|#n5^~scvB6#Pk%Ho!kQ>yYw((Dv{6=$g3jT1!u6gORW zx5#`7Wy-ZHRa~IxGHdrp(bm%lf>2%J660nj$fCqN(epv@y!l9s7@k6EvxS{AMP>WY zX4$@F8^kayphIx-RGO$+LYl9YdoI5d|4#q9##`_F5Xnx`&GPzp2fB{-{P@ATw=X@~ z_|&^UMWAKD;jjBKTK(~o?cUFRK8EX=6>cXpfzg4ZpMB>*w_^8GSiT-Jp|xBOnzM+j z*09-@-~qJ(eqWq5@R4i^u4^{McCP(!3}C|v_WsTR*bIUxN(Nx`u##3B4{sE`Z`v8w zAwIG`?1~PkID~W{uDzmqH98Pew_1(;x2%8r^vY{)_&J2K)cN{W+h5+g)ZcjP&Ci#O zgy|8K@4kyMfwilHd&6TDlhb%++Pk!>9HRld6HT7gwyZGrxS$}CsD6`>6!!2K1@Mjf z(P0WYB7V_OFZyeWrbOFb>O54BNXf~K&?}3=^v;v_wT{DKr?jN^DtN&DXwX%u?s*c6`%8>WFz z7}YW^tp0bp^NriE)AB6M2l<7rn7fzePtR*omOevpfm9n?}2V*+0iW;S)C zhg`NAjL?D=W#k*$aR{>pGf~lD-rVtD;5jW1_*Jn1j1=es@Kcx4ySM_bwcQCT=d+DV z>Sz~L=Hj@(X%31nK$mWI@7d>}ORB`K(p=+`UD)+99YUGQc7y^bHZ1F(8|tL0 zdK*DT0kSXG_{BKTpP2*2PecdKV9;dq$^ZZDP;Nyq1kp-&GI5eAyZsK!e3V zK@rPy*{(`KIfo+lc878mDKk^V#`VT05}64kBtk%DgwLrOvLMj5-;*GNKv6c6pzMuL z6EP%ob|_0IW}lLRXCP2!9wWhEw3LA7iF#1O1mIZ@Z=6&bz41F;@S_GvYAG-#CW3z{ zP3+6vHhvP&A3$##Vo9$dT^#MoGg^|MDm=Bt1d2RRwSZ<;ZHICpLBv5Xs!D?BH^(9_ z7`H=N&^v|Z-%mP}wNzG{aiFCsRgwzwq!N6obW9+7(R; z(SZ=23`|`>qil!LMGG{_Heq!BD>(Y-zV9wD)}hz25JA37YR%39;kI4y9pgtcUass6 zP24}ZY$vvYeI`zy&)A_X#nY3017ap*0&jx|mVwyGhg3;!keU53a}Uhm3BZI$N$6Se zLWlAmy1S0xKJm4G_U@sN_Tm=`$xWJSEwKU98rZ&)1R^*$$1vA3oG#&*%SMxY_~oGP zP&PFJatFLM-Ps%84IV-+Ow)T{C7cqUAvauy4C z(FRz&?6$Rypj{xO!`y=*J5o4@U8Q-(y5(*=YoKeZ+-1YdljXxkA#B)zo=FeQH#?Le zycNUmEEHWO9a=X^pb#&cOq7-`7UA87#|S22)<7RUtZo|(zibX=w;K3qur9vy#`MNV z6UUcf9ZwEnKCCp+OoBnF@OdbvH)ANXO0o~Pi9l8=x3))}L<#vO0-~O4!~--Ket?d} zJaqsj<@CD1%S2cTW%rOP{Vto%0sGW~1RMa_j^)5nil0Yw- z0EE#bP+l4#P^%PQ+N*oxu1Zq05xZ!bXfYTg>9c{(Iw*lnjR^>kz%lAN^zFce7rppy zY8zA~3GD=A6d*hze&l4D_wA~+O!56)BZTe_rEu}Ezi<4!kG|W#amBZ5{&XS2@6R~H z{9o^y*BkH4$~yX9U&@CgbOzX1bn9xqF|zh$Dh0Y5y*E0e90*$!ObrHY3Ok0`2=O~r zCuke6KrP9KOf?V(YDsM<6pX2nVoN%M$LT^q#FmtaF?1^27F*IcNX~XRB(|hCFvdcc zc)$=S-)acdk$g4?_>jRqxpI6M3vHZk?0c^3=byamYDNf;uB{3NlKW5IhnOS3DNkMV z?tK8?kJ}pmvp%&&eTVOVjHP`q34hN1@!aK}H(K!vI`~gf|Gv+FNEQD5Yd<~yX7k_l h&G-K)@HZb3BABY{)U1?^%I#E6`MGoTtustd{~yM6srvu` literal 0 HcmV?d00001 diff --git a/test/TestApps/PushNotificationsTestAppPackage/Images/Square150x150Logo.scale-200.png b/test/TestApps/PushNotificationsTestAppPackage/Images/Square150x150Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..af49fec1a5484db1d52a7f9b5ec90a27c7030186 GIT binary patch literal 2937 zcma)84OCO-8BSud5)jwMLRVKgX(S?$n?Ld|vrsm<$CF7)&zTbyy1FE5bU`Q17MRv`9ue$;R(@8kR;#vJ*IM0>cJIAOte!d7oRgdH zd%ySjdB6L9=gX^A6)VzH7p2l@v~3zJAMw|DFy#^)F@@F*`mqUn=Il>l)8_+ab;nOW{%+iPx z+s{Eu|&pIs)Z7{La9~?xKfyl z#43?gjEL15d4WbOZo#SiP%>DB^+BcnJ=7dHEe;r#G=tuw|ka z%q@}##Uh7;tc%L_64m(kHtw74ty%BJMb)_1)#S0j`)F8_1jF7vScpsnH=0V19bO8y zR`0SjIdCUo&=>JwMQF8KHA<{ODHTiQh}0^@5QRmCA?gOH6_H3K^-_sNB^RrdNuK-R zOO*vOrKCVvDwgUck`kF(E7j{I#iiN;b*ZdCt4m@HPA`EuEqGGf4%!K<;(=I=&Vyrw z%TwcWtxa}8mCZ%Cyf&ActJ6_$ox5z6-D!0-dvnRx6t7y3d+h6QYpKWO;8OdnvERo7 zuEf>ih5`wqY)~o@OeVt-wM?Q!>QzdGRj!bz6fzYrfw$hZfAKzr2-M+D+R>}~oT574c;_3zquHcElqKIsryILt3g8n3jcMb+j?i?-L3FpZJ z2WRVBRdDPc+G5aaYg#5hpE+6nQ|(VSoxT3|biF;BUq#==-27Xi=gihDPYP$7?=9cP zYKE$jeQ|3~_L0VG-(F~2ZPyD0=k{J4Q~h(t__{-mz_w8{JDY9{`1ouzz!Vr5!ECdE z6U~O1k8c}24V7~zzXWTV-Pe4)y}wQJS&q%H5`Fo_f_JvIU489aCX$;P`u#!I-=^4ijC2{&9!O&h>mi?9oYD=GC#%)6{GzN6nQYw+Fal50!#x^asjBBR50i`+mho*ttoqV)ubM2KD9S~k7+FR4>{29?6 z{!l6kDdyTN0YJ9LgkPWeXm|gyi@zM3?0@{&pXT12w|78&W-q!RRF)&iLCEZVH<|fR zN0fr2^t8H(>L?>K#>^+jWROLral(Qy-xoBq1U7A&DV||wClb)Otd9?(gZ|8znMF}D zf<1haWz^s0qgecz;RFGt0C-B4g`jNGHsFU+;{<%t65v^sjk^h$lmWn#B0#_)9ij&d z-~lc`A)YYExi^7sBuPM^Y|wA2g*5?`K?#7tzELQYNxGo$UB$4J8RJp1k(8Jj+~hMT zlN~>M@KTTh^--8y3PK_NZ@AC!{PT=CziBzGd+wTJ^@icH!Bd}%)g8V)%K?|c&WTUk zy}qv1C%(fjRoZ4ozC3{O%@5?)XzH35zHns$pgU*Q?fj4v?fp1Qbm+j;3l;9jam9Da zXVcKjPlQ73x78QPu|Ffm6x?`~e3oD=gl=4kYK?={kD5j~QCXU)`HSdduNNENzA*2$ zOm3PzF!lN5e*06-f1Uot67wY#{o-S1!KZ7E=!~7ynnk9_iJR#kFoNbAOT#^2Gd17F zMmvU6>lndZQGd|ax9kUoXXO+$N?|j@6qpsF&_j7YXvwo_C{JpmLw5&#e6k>atv%es z5)7r*Wvv_JkUpT}M!_o!nVlEk1Zbl=a*2hQ*<|%*K1Glj^FcF`6kTzGQ3lz~2tCc@ z&x|tj;aH&1&9HwcJBcT`;{?a+pnej;M1HO(6Z{#J!cZA04hnFl;NXA+&`=7bjW_^o zfC40u3LMG?NdPtwGl>Tq6u}*QG)}-y;)lu-_>ee3kibW(69n0$0Zy!}9rQz%*v1iO zT9_H>99yIrSPYVy6^);rR}7Yo=J_T@hi+qhTZXnVWyf;JDYm5#eYLTxr*?kiNn!+Y zQ+LUkBafNJ#rH#C(?d5^;gw9o#%daEI{mA*LHPIHPU`#|H$hD zwm>0&+kahQ)E#%~k>&5@&#Vg82H?s%71=)(soi@174pi9--2{w{1$}Sz4zGn3Du&x bht0Iza^2ykEt4(epJ78uh5nDlX8(TxzDYwP literal 0 HcmV?d00001 diff --git a/test/TestApps/PushNotificationsTestAppPackage/Images/Square44x44Logo.scale-200.png b/test/TestApps/PushNotificationsTestAppPackage/Images/Square44x44Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..ce342a2ec8a61291ba76c54604aea7e9d20af11b GIT binary patch literal 1647 zcmaJ?eM}Q)7(e+G1Q(|`V9JhTI2>MkceK4;p;PR&$Pi?ejk3YQ_3o`S&|W_dsOZ8# zWPTt69g`t$ab`0cj-Y0yiBSOqmd)tG7G(}M5aP0_%&9TijB#&)I{zSE^4@#z^FF`l z`8{8`o%wlL(UI|y2!cdsuVamHH~H86F!*-15em4)NqUpCQM5?aoC_eCf@lV4wvF2a zjDQn1JBL69f&@2M3rvzJcfE!eZ8FZUBlFlC5RD)it33{mF9#B82AiyQE%w)`vlwa> zv{<1sm&kSKK$&%2jSFn7$t&P%%6Ue>R=EAnG8N7fqynWG8L3p!4801a;8{+nliO(qd(jNJ_?+9W3#hLIDLoT6~3fx9=`CC-D}-AMrpEO7HK zt3$GicGPc?GmDjy7K2P@La;eu4!$zWCZ`ym{Z$b zu-O6RM&K4JT|BIZB`E-gxqG%FzanI#+2FFmqHqXG7yxWB=w55RGOM)$xMb(>kSNR z2w=1AZi%z=AmG~yea~XaXJR!v7vLn(RUnELfiB1|6D84ICOS}^Zo2AdN}<&*h}G_u z{xZ!(%>tLT3J3<5XhWy-tg+6)0nmUUENLW8TWA{R6bgVd3X;anYFZ^IRis*_P-C-r z;i>%1^eL3UI2-{w8nuFFcs0e~7J{O2k^~Ce%+Ly4U?|=!0LH=t6()xi<^I-rs+9sF z*q{E-CxZbGPeu#a;XJwE;9S1?#R&uns>^0G3p`hEUF*v`M?@h%T%J%RChmD|EVydq zmHWh*_=S%emRC*mhxaVLzT@>Z2SX0u9v*DIJ@WC^kLVdlGV6LpK$KIrlJqc zpJ921)+3JJdTx|<`G&kXpKkjGJv=76R`yYIQ{#c-`%+`#V(7}Q;&@6U8!Td1`d;?N z_9mnI#?AA}4J!r)LN4!E-@H5eXauuB7TOawS>Y|{-P?NNx-lq+z1W-+y(;39P&&LP zL{N80?&=C*qKmdA^moMZRuPcD!B<*mq$ch=0Cnlitw#txRWhb3%TQvPqjkC`F69G4b! ze7z9MZ#+;_#l?H37UqUhDFb^l&s2{oM$3I0o^Q!yx;;V)QmCMo)Tb_ui|mit8MS?U zm##6$sZZ1$@|s%?l@>4Z<*Q}sRBSKMhb4I{e5LdEhsHIHTe8Bod5c>6QtT>$XgUBz z6MK`kO$=jmt@FqggOhJ5j~e@ygRbG;<{Vu)*+nn9aQeo0;$#j;|MS=S$&L?BeV25z xs3B`@=#`5TF{^6(A1rvdY@|-RtQ|iS5{tyX+wH?;n8E)G$kykv-D^wh{{!TZT%7;_ literal 0 HcmV?d00001 diff --git a/test/TestApps/PushNotificationsTestAppPackage/Images/Square44x44Logo.targetsize-24_altform-unplated.png b/test/TestApps/PushNotificationsTestAppPackage/Images/Square44x44Logo.targetsize-24_altform-unplated.png new file mode 100644 index 0000000000000000000000000000000000000000..f6c02ce97e0a802b85f6021e822c89f8bf57d5cd GIT binary patch literal 1255 zcmaJ>TWs4@7*5+{G#S+&C!qC#> zf>5N3P6jO*Cz>ug*(_DmW=)kea&m$gZ^+nyiF`;j%w@}y8)>p*SH}C`m?DXeieF2U zyQHecc_L%Gh!7GMt+hG06y;+|p4>m~}PjA}rKViGiEnn7G0ZO<>G|7q;2?NwGCM3s?eued6%hd$B+ z*kQJ{#~$S=DFE(%=E+UkmlEI*%3llUf~8Ja9YU1Vui0IbGBkW_gHB%Rd&!!ioX zs40O?i9I{};kle7GMvE7(rk`la=gTI)47=>%?q@^iL-nUo3}h4S}N-KHn8t5mVP8w z&bSErwp+37 zNJJ8?a|{r5Q3R0Z5s-LB1WHOwYC@7pCHWND#cL1cZ?{kJ368_*(UDWUDyb<}0y@o# zfMF016iMWPCb6obAxT$JlB6(2DrlXDTB&!0`!m??4F(qWMhjVZo?JXQmz`1*58Z=& zcDmB|S-E@j?BoFGix0flckqdS4jsPNzhfWyWIM98GxcLs89C(~dw%$_t;JjX-SD}E zfiGV;{8Q%8r}w9x>EEigW81>`kvnU@pK)4+xk9@+bNj9L!AAZ@SZ@q|)&BmY3+HZx zul~BeG4|}-;L%cHViQGQX?^zFfO0&#cHwel=d`lH9sJ-@Sl@n*(8J2>%Ac`IxyY?Q z{=GhWvC#gu-~Ia7*n{=+;qM?Ul_wy1+u7ho;=`>EwP^g~R@{unBds`!#@}tluZQpS zm)M~nYEifJWJGx?_6DcTy>#uh%>!H9=hb^(v`=m3F1{L>db=<5_tm+_&knAQ2EU$s Mu9UqpbNZeC0BbUo^Z)<= literal 0 HcmV?d00001 diff --git a/test/TestApps/PushNotificationsTestAppPackage/Images/StoreLogo.png b/test/TestApps/PushNotificationsTestAppPackage/Images/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..7385b56c0e4d3c6b0efe3324aa1194157d837826 GIT binary patch literal 1451 zcmaJ>eN5D57_Z|bH;{0+1#mbl)eTU3{h)Wf7EZV?;HD@XL@{B`Ui%(2aMxQ~xdXSv z5nzWi(LW)U2=Vc-cY@s7nPt{i0hc6!7xN4NNHI#EQl>YNBy8l4%x9gr_W-j zEZMQmmTIy(>;lblRfh`dIyTgc9W5d!VP$L4(kKrN1c5G~(O_#xG zAJCNTstD^5SeXFB+&$h=ToJP2H>xr$iqPs-#O*;4(!Fjw25-!gEb*)mU}=)J;Iu>w zxK(5XoD0wrPSKQ~rbL^Cw6O_03*l*}i=ydbu7adJ6y;%@tjFeXIXT+ms30pmbOP%Q zX}S;+LBh8Tea~TSkHzvX6$rYb)+n&{kSbIqh|c7hmlxmwSiq5iVhU#iEQ<>a18|O^Sln-8t&+t`*{qBWo5M?wFM(JuimAOb5!K#D}XbslM@#1ZVz_;!9U zpfEpLAOz=0g@bd6Xj_ILi-x^!M}73h^o@}hM$1jflTs|Yuj9AL@A3<-?MV4!^4q`e z)fO@A;{9K^?W?DbnesnPr6kK>$zaKo&;FhFd(GYFCIU^T+OIMb%Tqo+P%oq(IdX7S zf6+HLO?7o0m+p>~Tp5UrXWh!UH!wZ5kv!E`_w)PTpI(#Iw{AS`gH4^b(bm^ZCq^FZ zY9DD7bH}rq9mg88+KgA$Zp!iWncuU2n1AuIa@=sWvUR-s`Qb{R*kk(SPU^`$6BXz8 zn#7yaFOIK%qGxyi`dYtm#&qqox0$h=pNi#u=M8zUG@bpiZ=3sT=1}Trr}39cC)H|v zbL?W)=&s4zrh)7>L(|cc%$1#!zfL?HjpeP%T+x_a+jZ16b^iKOHxFEX$7d|8${H-* zIrOJ5w&i$>*D>AKaIoYg`;{L@jM((Kt?$N$5OnuPqVvq**Nm}(f0wwOF%iX_Pba;V z;m@wxX&NcV3?<1+u?A{y_DIj7#m3Af1rCE)o`D&Y3}0%7E;iX1yMDiS)sh0wKi!36 zL!Wmq?P^Ku&rK~HJd97KkLTRl>ScGFYZNlYytWnhmuu|)L&ND8_PmkayQb{HOY640 bno1(wj@u8DCVuFR|31B*4ek@pZJqxCDDe1x literal 0 HcmV?d00001 diff --git a/test/TestApps/PushNotificationsTestAppPackage/Images/Wide310x150Logo.scale-200.png b/test/TestApps/PushNotificationsTestAppPackage/Images/Wide310x150Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..288995b397fdbef1fb7e85afd71445d5de1952c5 GIT binary patch literal 3204 zcmbVPeQXow8NYmBd90>}0NP?GhXW~VaeThm=a0tV#EwJMI!)6M3}|c4_Bl3=Kd>G0 z(GHx1wl<7(tP?FsOQkTilSo*iIvF%uArExJ73~P zSv1xEy!U(Wd4A9D`FQV@W3@F^qJ@PEF$@z`Z!*BbFsS(^?B zyiAzJ+q})bkgiQHWqEb*jJD-coHYr1^iocg)l!Qa{Xqs-l~6J}p-|##ZHYofskQ3$ zI0;xzXyhazBeXhIsg5A=%ufo@f)1yy&ScKS0;HF^!r_2UE^lpZEom(+@duma3awTv zCrCL-%D_SvYWIcdHkmI}#50(fkUi)Qgx!80ju>g1za^}ff>JI8Z@^-iCiaCgg@TgF z+vtE?Q9{VQUX&MW9SYYmGcxA14%N2@7FwBTD4N<(2{nWgV8$e3?-F=L^&FrtWn~(U_Q~~^uYiyeY6-KoTnfh9AWz@ zIKje0)u!_Lw)E}G!#kEfwKVdNt(UAf9*f>tEL_(=xco-T%jTi@7YlC3hs2ik%Le0H ztj}RTeCF(5mwvi3_56>-yB?l;J>-1%!9~=fs|QcNG3J~a@JCu`4SB460s0ZO+##4fFUSGLcj_ja^fL4&BKALfb#$6$O?>P@qx2Agl^x0i&ugt zsy5Pyu=()`7HRMG3IB7F1@`_ z+-!J%#i6e^U$e#+C%Q>_qVRzWRsG^W_n+@OcX@vzI&z;mzHNb!GQ?LWA(wtpqHqTM z1OFw_{Zn?fD)p)`c`kOgv{de=v@suGRqY{N^U7gI1VF3*F=obwaXI6ob5__Yn zVTguS!%(NI09J8x#AO_aW!9W7k*UvB;IWDFC3srwftr{kHj%g)fvnAm;&h_dnl~

MY- zf+K}sCe8qU6Ujs`3ua{U0Of$R_gVQBuUA za0v=mu#vIOqiiAZOr&h*$WyOw&k-xr$;G4Ixa!#TJNr>95(h>l%)PUy4p+^SgR(uR zta%k*?ny-+nAr8spEk1fo{J4i!b^Fia`N{_F6@zidA2ZTTrjl#^5Z-2KfB@Cu}l9s z(*|Z2jc?p~vn2f)3y9i*7zJV1L{$?|&q)4oaT;uXi6>1GkRXVTOzAz(RHEmr=eFIi z`}<>-Q?K0GN8!IYxeP1XKXO+jsJbp~o^);Bc;%b7Flpe7;1`Ny@3r7ZR;?R)aJt8C ziNlEC<@3f_lIV4TwV}&e;D!Ee5_|e#g0LUh=5vmYWYm7&2h*M>QPKvGh9-)wfMMW3 z8J9b%1k7dzPzO0_NGQy92BZ^FR6R~6;^6?lqO;-QUP4BY%cG%3vEhbm#>4vIhPBh3 z-+pZGjh$x%Hp{?=FHsMp0&wNPlj00us{&`1ZOZTqs8%4X&xH=UDr*xyBW(Zp&Em94 zf)ZSfn#yg0N)>!1kWdkqJ^S*z0FF5|fj&qcE#Na|%OY0$uO>!&hP+1ywfD_WXk@4J(?MBftK7>$Nvqh@tDuarN%PrTLQ2Uzysx>UV=V zk^RrDSvdQ?0;=hY67EgII-f4`t=+i*yS=Y~!XlqIy_4x&%+OdfbKOFPXS2X5%4R{N z$SQMX^AK6(fA + + + + + + + PushNotificationsTestAppPackage + vemancha + Images\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + ReunionTestProtocol + + + + + + + + + + + + + + + + + + diff --git a/test/TestApps/PushNotificationsTestAppPackage/PushNotificationsTestAppPackage.wapproj b/test/TestApps/PushNotificationsTestAppPackage/PushNotificationsTestAppPackage.wapproj new file mode 100644 index 0000000000..adbec5a233 --- /dev/null +++ b/test/TestApps/PushNotificationsTestAppPackage/PushNotificationsTestAppPackage.wapproj @@ -0,0 +1,117 @@ + + + + 15.0 + + + + Debug + x86 + + + Release + x86 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM + + + Release + ARM + + + Debug + ARM64 + + + Release + ARM64 + + + Debug + AnyCPU + + + Release + AnyCPU + + + + $(MSBuildExtensionsPath)\Microsoft\DesktopBridge\ + + + + d012e4bb-f16b-472d-a26d-d449cefa988e + 10.0.19041.0 + 10.0.17763.0 + en-US + True + ..\PushNotificationsTestApp\PushNotificationsTestApp.vcxproj + true + False + $(SolutionDir)temp\MSTest.pfx + SHA256 + True + True + $(Platform) + 0 + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + + Designer + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/inc/TestDef.h b/test/inc/TestDef.h index f268186e3d..aadee21f36 100644 --- a/test/inc/TestDef.h +++ b/test/inc/TestDef.h @@ -17,6 +17,9 @@ static const std::wstring c_testFilePhaseEventName = L"ReunionTestFilePhaseEvent static const std::wstring c_testStartupPhaseEventName = L"ReunionTestStartupPhaseEventName"; static const std::wstring c_testInstanceRedirectedPhaseEventName = L"ReunionTestInstanceRedirectedPhaseEventName"; +static const winrt::hstring c_rawNotificationPayload = L""; +static const IID c_comServerId = winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2"); +static const IID c_fakeComServerId = winrt::guid("00000000-0000-0000-0000-000000000001"); #ifndef WIDEN2 #define WIDEN2(x) L ## x From 22b3ef9648e228472c4142d37db6b67d86ce2c2b Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Fri, 14 May 2021 14:47:58 -0700 Subject: [PATCH 06/53] Added PushNotification classes to NuSpecs --- build/NuSpecs/AppxManifest.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build/NuSpecs/AppxManifest.xml b/build/NuSpecs/AppxManifest.xml index 2c0916dfd9..036003dd30 100644 --- a/build/NuSpecs/AppxManifest.xml +++ b/build/NuSpecs/AppxManifest.xml @@ -37,6 +37,14 @@ + + + + + + + + From d6ea25fdd18c3771f3d2edc5af10fee66b49ea1b Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Mon, 17 May 2021 00:19:24 -0700 Subject: [PATCH 07/53] Fix some PR comments surrounding background activation --- dev/AppLifecycle/AppInstance.cpp | 8 +- .../GetRawNotificationEventArgs.h | 4 +- .../PushNotificationActivationInfo.cpp | 17 +- .../PushNotificationActivationInfo.h | 6 +- .../PushNotificationBackgroundTask.cpp | 8 +- .../PushNotificationBackgroundTask.h | 6 +- .../PushNotificationManager.cpp | 26 +-- .../PushNotificationManager.h | 2 +- .../PushNotificationReceivedEventArgs.cpp | 54 ++--- .../PushNotificationReceivedEventArgs.h | 8 +- .../PushNotificationRegistrationToken.cpp | 10 +- .../PushNotificationRegistrationToken.h | 9 +- dev/PushNotifications/PushNotifications.idl | 190 +++++++++--------- 13 files changed, 155 insertions(+), 193 deletions(-) diff --git a/dev/AppLifecycle/AppInstance.cpp b/dev/AppLifecycle/AppInstance.cpp index 5c975d7d3f..b17938e0cc 100644 --- a/dev/AppLifecycle/AppInstance.cpp +++ b/dev/AppLifecycle/AppInstance.cpp @@ -313,18 +313,16 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation if (HasIdentity()) { - auto pushArgs = GetRawNotificationEventArgs::GetRawNotificationEventArgs(); - if (pushArgs) + if (auto pushArgs = PushNotifications::GetRawNotificationEventArgs()) { data = pushArgs; kind = ExtendedActivationKind::Push; } else { - auto args = winrt::Windows::ApplicationModel::AppInstance::GetActivatedEventArgs(); - if (args) + if (auto args = winrt::Windows::ApplicationModel::AppInstance::GetActivatedEventArgs()) { - data = args.as(); + data = args; kind = static_cast(args.Kind()); } } diff --git a/dev/PushNotifications/GetRawNotificationEventArgs.h b/dev/PushNotifications/GetRawNotificationEventArgs.h index 8796ecb92f..362f73b07b 100644 --- a/dev/PushNotifications/GetRawNotificationEventArgs.h +++ b/dev/PushNotifications/GetRawNotificationEventArgs.h @@ -6,9 +6,9 @@ using namespace winrt; using namespace winrt::Windows::Foundation; constexpr PCWSTR pushServerArgument = L"-ReunionPushServer"; -namespace GetRawNotificationEventArgs +namespace winrt::Microsoft::Windows::PushNotifications { - static Windows::Foundation::IInspectable GetRawNotificationEventArgs() + static winrt::Windows::Foundation::IInspectable GetRawNotificationEventArgs() { winrt::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs args = nullptr; diff --git a/dev/PushNotifications/PushNotificationActivationInfo.cpp b/dev/PushNotifications/PushNotificationActivationInfo.cpp index 82c71d48dc..45d00050c1 100644 --- a/dev/PushNotifications/PushNotificationActivationInfo.cpp +++ b/dev/PushNotifications/PushNotificationActivationInfo.cpp @@ -12,30 +12,29 @@ namespace winrt namespace winrt::Microsoft::Windows::PushNotifications::implementation { - PushNotificationActivationInfo::PushNotificationActivationInfo(winrt::PushNotificationRegistrationKind const& kind, winrt::guid const& taskClsid) - { - m_kind = kind; - m_taskClsid = taskClsid; - } + PushNotificationActivationInfo::PushNotificationActivationInfo(winrt::PushNotificationRegistrationKind const& kind, winrt::guid const& taskClsid) : m_kind(kind), m_taskClsid(taskClsid) {} + winrt::guid PushNotificationActivationInfo::TaskClsid() { - auto lock = m_lock.lock_shared(); return m_taskClsid; } winrt::PushNotificationRegistrationKind PushNotificationActivationInfo::Kind() { - auto lock = m_lock.lock_shared(); return m_kind; } + winrt::com_array PushNotificationActivationInfo::GetConditions() { auto lock = m_lock.lock_shared(); - return winrt::com_array(m_backgroundConditions.begin(), m_backgroundConditions.end()); + return { m_backgroundConditions.begin(), m_backgroundConditions.end() }; } + void PushNotificationActivationInfo::SetConditions(array_view conditions) { + // Need to destroy old conditions outside of lock. + auto replacement = winrt::com_array(conditions.begin(), conditions.end()); auto lock = m_lock.lock_exclusive(); - m_backgroundConditions = winrt::com_array(conditions.begin(), conditions.end()); + swap(m_backgroundConditions, replacement); } } diff --git a/dev/PushNotifications/PushNotificationActivationInfo.h b/dev/PushNotifications/PushNotificationActivationInfo.h index 4e10a3bead..9ce88c6453 100644 --- a/dev/PushNotifications/PushNotificationActivationInfo.h +++ b/dev/PushNotifications/PushNotificationActivationInfo.h @@ -5,8 +5,6 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { struct PushNotificationActivationInfo : PushNotificationActivationInfoT { - PushNotificationActivationInfo() = default; - PushNotificationActivationInfo(Microsoft::Windows::PushNotifications::PushNotificationRegistrationKind const& kind, winrt::guid const& taskClsid); winrt::guid TaskClsid(); Microsoft::Windows::PushNotifications::PushNotificationRegistrationKind Kind(); @@ -14,8 +12,8 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation void SetConditions(array_view conditions); private: - Microsoft::Windows::PushNotifications::PushNotificationRegistrationKind m_kind; - winrt::guid m_taskClsid; + const Microsoft::Windows::PushNotifications::PushNotificationRegistrationKind m_kind; + const winrt::guid m_taskClsid; winrt::com_array m_backgroundConditions{}; wil::srwlock m_lock; }; diff --git a/dev/PushNotifications/PushNotificationBackgroundTask.cpp b/dev/PushNotifications/PushNotificationBackgroundTask.cpp index 505ee44ff6..fec7c8dd29 100644 --- a/dev/PushNotifications/PushNotificationBackgroundTask.cpp +++ b/dev/PushNotifications/PushNotificationBackgroundTask.cpp @@ -17,9 +17,11 @@ namespace winrt wil::unique_handle g_waitHandleForArgs; winrt::PushNotificationReceivedEventArgs g_activatedEventArgs{ nullptr }; -void PushNotificationBackgroundTask::Run(winrt::IBackgroundTaskInstance taskInstance) +void PushNotificationBackgroundTask::Run(winrt::IBackgroundTaskInstance const& taskInstance) { + { + auto lock = g_lock.lock(); + g_activatedEventArgs = winrt::PushNotificationReceivedEventArgs::CreateFromBackgroundTaskInstance(taskInstance); + } SetEvent(g_waitHandleForArgs.get()); - auto lock = g_lock.lock(); - g_activatedEventArgs = winrt::PushNotificationReceivedEventArgs::CreateFromBackgroundTaskInstance(taskInstance); } diff --git a/dev/PushNotifications/PushNotificationBackgroundTask.h b/dev/PushNotifications/PushNotificationBackgroundTask.h index 31064900d1..331fb7f3af 100644 --- a/dev/PushNotifications/PushNotificationBackgroundTask.h +++ b/dev/PushNotifications/PushNotificationBackgroundTask.h @@ -4,11 +4,11 @@ struct PushNotificationBackgroundTask : winrt::implements -#include +#include #include "PushNotificationBackgroundTask.h" #include #include #include "PushNotificationChannel.h" #include "externs.h" +#include -constexpr PCWSTR backgroundTaskName = L"PushBackgroundTaskName"; +using namespace std::literals; + +constexpr std::wstring_view backgroundTaskName = L"PushBackgroundTaskName"sv; namespace winrt { @@ -184,15 +187,8 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation if (WI_IsFlagSet(details.Kind(), PushNotificationRegistrationKind::PushTrigger)) { - bool taskRegistered = false; - for (auto task : BackgroundTaskRegistration::AllTasks()) - { - if (task.Value().Name() == backgroundTaskName) - { - taskRegistered = true; - break; - } - } + auto tasks = BackgroundTaskRegistration::AllTasks(); + bool taskRegistered = std::any_of(begin(tasks), end(tasks), [&](auto&& task) { return task.Value().Name() == backgroundTaskName; }); if (!taskRegistered) { @@ -214,6 +210,10 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation builder.AddCondition(condition); } } + else + { + throw winrt::hresult_not_implemented(); + } } registeredTask = builder.Register(); @@ -255,9 +255,9 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } } - if (WI_IsFlagSet(kind, PushNotificationRegistrationKind::ComActivator) && (token.Cookie() != 0)) + if (WI_IsFlagSet(kind, PushNotificationRegistrationKind::ComActivator) && token.Cookie()) { - THROW_IF_FAILED(::CoRevokeClassObject(static_cast(token.Cookie()))); + LOG_IF_FAILED(::CoRevokeClassObject(static_cast(token.Cookie()))); } } } diff --git a/dev/PushNotifications/PushNotificationManager.h b/dev/PushNotifications/PushNotificationManager.h index 403db2c649..572cdf5dc3 100644 --- a/dev/PushNotifications/PushNotificationManager.h +++ b/dev/PushNotifications/PushNotificationManager.h @@ -5,7 +5,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { struct PushNotificationManager { - PushNotificationManager() = default; + PushNotificationManager() = delete; static Microsoft::Windows::PushNotifications::PushNotificationRegistrationToken RegisterActivator(Microsoft::Windows::PushNotifications::PushNotificationActivationInfo const& details); static void UnregisterActivator(Microsoft::Windows::PushNotifications::PushNotificationRegistrationToken const& token, Microsoft::Windows::PushNotifications::PushNotificationRegistrationKind const& kind); diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp index 0562562b65..657511b635 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp @@ -17,25 +17,20 @@ namespace winrt namespace winrt::Microsoft::Windows::PushNotifications::implementation { - PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::IBackgroundTaskInstance const& backgroundTask) + winrt::com_array GetRawPayload(RawNotification const& rawNotification) { - m_backgroundTaskInstance = backgroundTask; - - // Need to process the RawNotification payload here because TriggerDetails is set to nullptr leaving IBackgroundTaskInstance::Run - auto triggerDetails = m_backgroundTaskInstance.TriggerDetails(); - RawNotification rawNotification = triggerDetails.as(); - IBuffer rawContentAsBuffer = rawNotification.ContentBytes(); DataReader dataReader = DataReader::FromBuffer(rawContentAsBuffer); - m_backgroundPayload = winrt::com_array(rawContentAsBuffer.Length()); - dataReader.ReadBytes(m_backgroundPayload); + winrt::com_array rawPayload = winrt::com_array(rawContentAsBuffer.Length()); + dataReader.ReadBytes(rawPayload); + + return rawPayload; } - PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::PushNotificationReceivedEventArgs const& args) - { - m_args = args; - } + PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::IBackgroundTaskInstance const& backgroundTask): m_backgroundTaskInstance(backgroundTask), m_rawNotification(GetRawPayload(backgroundTask.TriggerDetails().as())) {} + + PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::PushNotificationReceivedEventArgs const& args): m_args(args), m_rawNotification(GetRawPayload(args.RawNotification())) {} winrt::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs PushNotificationReceivedEventArgs::CreateFromBackgroundTaskInstance(winrt::IBackgroundTaskInstance const& backgroundTask) { @@ -49,50 +44,28 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation winrt::com_array PushNotificationReceivedEventArgs::Payload() { - auto lock = m_lock.lock_shared(); - winrt::com_array payload{}; - if (m_args) - { - RawNotification rawNotification = m_args.RawNotification(); - - IBuffer rawContentAsBuffer = rawNotification.ContentBytes(); - DataReader dataReader = DataReader::FromBuffer(rawContentAsBuffer); - - payload = winrt::com_array(rawContentAsBuffer.Length()); - dataReader.ReadBytes(payload); - } - else if (m_backgroundTaskInstance) - { - return winrt::com_array(m_backgroundPayload.begin(), m_backgroundPayload.end()); - } - return payload; + return { m_rawNotification.begin(), m_rawNotification.end() }; } winrt::BackgroundTaskDeferral PushNotificationReceivedEventArgs::GetDeferral() { - auto lock = m_lock.lock_shared(); if (m_backgroundTaskInstance) { return m_backgroundTaskInstance.GetDeferral(); } - return nullptr; + // winrt::throw_hresult(); } winrt::event_token PushNotificationReceivedEventArgs::Canceled(winrt::BackgroundTaskCanceledEventHandler const& handler) { + if (m_backgroundTaskInstance) { - auto lock = m_lock.lock_shared(); - if (m_backgroundTaskInstance) - { - return m_backgroundTaskInstance.Canceled(handler); - } + return m_backgroundTaskInstance.Canceled(handler); } - return winrt::event_token{}; } void PushNotificationReceivedEventArgs::Canceled(winrt::event_token const& token) noexcept { - auto lock = m_lock.lock_shared(); if (m_backgroundTaskInstance) { m_backgroundTaskInstance.Canceled(token); @@ -100,7 +73,6 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } bool PushNotificationReceivedEventArgs::Handled() { - auto lock = m_lock.lock_shared(); if (m_args) { return m_args.Cancel(); @@ -109,10 +81,10 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } void PushNotificationReceivedEventArgs::Handled(bool value) { - auto lock = m_lock.lock_shared(); if (m_args) { m_args.Cancel(value); } } } + diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.h b/dev/PushNotifications/PushNotificationReceivedEventArgs.h index e006d72a54..1f97c44101 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.h +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.h @@ -5,6 +5,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { struct PushNotificationReceivedEventArgs : PushNotificationReceivedEventArgsT { + PushNotificationReceivedEventArgs() = delete; PushNotificationReceivedEventArgs(winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance const& backgroundTask); PushNotificationReceivedEventArgs(winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs const& args); @@ -18,10 +19,9 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation void Handled(bool value); private: - winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance m_backgroundTaskInstance = nullptr; - winrt::com_array m_backgroundPayload{}; - winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs m_args = nullptr; - wil::srwlock m_lock; + const winrt::com_array m_rawNotification{}; + const winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance m_backgroundTaskInstance = nullptr; + const winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs m_args = nullptr; }; } namespace winrt::Microsoft::Windows::PushNotifications::factory_implementation diff --git a/dev/PushNotifications/PushNotificationRegistrationToken.cpp b/dev/PushNotifications/PushNotificationRegistrationToken.cpp index 60342fa4d6..2a10782f54 100644 --- a/dev/PushNotifications/PushNotificationRegistrationToken.cpp +++ b/dev/PushNotifications/PushNotificationRegistrationToken.cpp @@ -6,19 +6,15 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { - PushNotificationRegistrationToken::PushNotificationRegistrationToken(uint64_t cookie, winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration const& taskRegistration) - { - m_cookie = cookie; - m_taskRegistration = taskRegistration; - } + PushNotificationRegistrationToken::PushNotificationRegistrationToken(uint64_t const& cookie, winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration const& taskRegistration): m_cookie(cookie), m_taskRegistration(taskRegistration) { } + uint64_t PushNotificationRegistrationToken::Cookie() { - auto lock = m_lock.lock_shared(); return m_cookie; } + winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration PushNotificationRegistrationToken::TaskRegistration() { - auto lock = m_lock.lock_shared(); return m_taskRegistration; } } diff --git a/dev/PushNotifications/PushNotificationRegistrationToken.h b/dev/PushNotifications/PushNotificationRegistrationToken.h index c164ac93c0..832b71a94f 100644 --- a/dev/PushNotifications/PushNotificationRegistrationToken.h +++ b/dev/PushNotifications/PushNotificationRegistrationToken.h @@ -5,16 +5,13 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { struct PushNotificationRegistrationToken : PushNotificationRegistrationTokenT { - PushNotificationRegistrationToken() = default; - - PushNotificationRegistrationToken(uint64_t cookie, winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration const& taskRegistration); + PushNotificationRegistrationToken(uint64_t const& cookie, winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration const& taskRegistration); uint64_t Cookie(); winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration TaskRegistration(); private: - uint64_t m_cookie; - winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration m_taskRegistration = nullptr; - wil::srwlock m_lock; + const uint64_t m_cookie; + const winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration m_taskRegistration; }; } namespace winrt::Microsoft::Windows::PushNotifications::factory_implementation diff --git a/dev/PushNotifications/PushNotifications.idl b/dev/PushNotifications/PushNotifications.idl index dac0a3dd3b..a841fd41fc 100644 --- a/dev/PushNotifications/PushNotifications.idl +++ b/dev/PushNotifications/PushNotifications.idl @@ -9,126 +9,126 @@ namespace Microsoft.Windows.PushNotifications // Initialize using the IBackgroundInstance: used specifically for the Background Activation scenario static PushNotificationReceivedEventArgs CreateFromBackgroundTaskInstance(Windows.ApplicationModel.Background.IBackgroundTaskInstance backgroundTask); -// Initialize using the PushNotificationEventArgs from Windows: used specifically for in-memory event handling when app is already in foreground -static PushNotificationReceivedEventArgs CreateFromPushNotificationReceivedEventArgs(Windows.Networking.PushNotifications.PushNotificationReceivedEventArgs args); + // Initialize using the PushNotificationEventArgs from Windows: used specifically for in-memory event handling when app is already in foreground + static PushNotificationReceivedEventArgs CreateFromPushNotificationReceivedEventArgs(Windows.Networking.PushNotifications.PushNotificationReceivedEventArgs args); -// The Push payload -byte[] Payload { get; }; + // The Push payload + byte[] Payload { get; }; -// Gets a deferral to run under specific modes like low power mode -Windows.ApplicationModel.Background.BackgroundTaskDeferral GetDeferral(); + // Gets a deferral to run under specific modes like low power mode + Windows.ApplicationModel.Background.BackgroundTaskDeferral GetDeferral(); -// Subscribe to Cancelled event handler to be signalled when resource policies are no longer true like 30s wallclock timer -event Windows.ApplicationModel.Background.BackgroundTaskCanceledEventHandler Canceled; + // Subscribe to Cancelled event handler to be signalled when resource policies are no longer true like 30s wallclock timer + event Windows.ApplicationModel.Background.BackgroundTaskCanceledEventHandler Canceled; -// Set to true to prevent proceeding launch due to Background Activation: false by default -Boolean Handled; -}; + // Set to true to prevent proceeding launch due to Background Activation: false by default + Boolean Handled; + }; -[flags] -enum PushNotificationRegistrationKind -{ - PushTrigger = 0x1, // Registers a Push Trigger with Background Infrastructure - ComActivator = 0x2, // Registers the Project Reunion Background Task component as an InProc COM server -}; + [flags] + enum PushNotificationRegistrationKind + { + PushTrigger = 0x1, // Registers a Push Trigger with Background Infrastructure + ComActivator = 0x2, // Registers the Project Reunion Background Task component as an InProc COM server + }; -// An abstraction over the activation Registration flow -runtimeclass PushNotificationActivationInfo -{ - // Initialize using a RegistrationKind 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 Project Reunion Background Task component will be Registered as an InProc COM server - PushNotificationActivationInfo(PushNotificationRegistrationKind kind, Guid taskClsid); + // An abstraction over the activation Registration flow + runtimeclass PushNotificationActivationInfo + { + // Initialize using a RegistrationKind 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 Project Reunion Background Task component will be Registered as an InProc COM server + PushNotificationActivationInfo(PushNotificationRegistrationKind kind, Guid taskClsid); -// The CLSID associated with the Client COM server that Project Reunion will activate -Guid TaskClsid{ get; }; + // The CLSID associated with the Client COM server that Project Reunion will activate + Guid TaskClsid{ get; }; -PushNotificationRegistrationKind Kind{ get; }; + PushNotificationRegistrationKind Kind{ get; }; -// The conditions under which Push Triggers would execute -Windows.ApplicationModel.Background.IBackgroundCondition[] GetConditions(); -void SetConditions(Windows.ApplicationModel.Background.IBackgroundCondition[] conditions); -}; + // The conditions under which Push Triggers would execute + Windows.ApplicationModel.Background.IBackgroundCondition[] GetConditions(); + void SetConditions(Windows.ApplicationModel.Background.IBackgroundCondition[] conditions); + }; -enum PushNotificationChannelStatus -{ - InProgress, // The request is in progress and there is no retry operation - InProgressRetry, // The request is in progress and is in a backoff retry state. Check ExtendedError for HRESULT for retryable error. - CompletedSuccess, // The request completed successfully - CompletedFailure, // The request failed with some critical internal error. Check ExtendedError for HRESULT -}; - -// The PushNotificationChannel Progress result -struct PushNotificationCreateChannelStatus -{ - // The last extended error we failed Channel requests on that caused the inprogress retry status. S_OK if this is just progress status. - HRESULT extendedError; + enum PushNotificationChannelStatus + { + InProgress, // The request is in progress and there is no retry operation + InProgressRetry, // The request is in progress and is in a backoff retry state. Check ExtendedError for HRESULT for retryable error. + CompletedSuccess, // The request completed successfully + CompletedFailure, // The request failed with some critical internal error. Check ExtendedError for HRESULT + }; + + // The PushNotificationChannel Progress result + struct PushNotificationCreateChannelStatus + { + // The last extended error we failed Channel requests on that caused the inprogress retry status. S_OK if this is just progress status. + HRESULT extendedError; - // Either InProgress or InProgressRetry status - PushNotificationChannelStatus status; + // Either InProgress or InProgressRetry status + PushNotificationChannelStatus status; - // Total Retries so far - UInt32 retryCount; -}; + // Total Retries so far + UInt32 retryCount; + }; -runtimeclass PushNotificationChannel -{ - PushNotificationChannel(Windows.Networking.PushNotifications.PushNotificationChannel channel); + runtimeclass PushNotificationChannel + { + PushNotificationChannel(Windows.Networking.PushNotifications.PushNotificationChannel channel); -// The Channel Uri for app to Post a notification to. -Windows.Foundation.Uri Uri { get; }; + // The Channel Uri for app to Post a notification to. + Windows.Foundation.Uri Uri { get; }; -// Expiration of the Channel -Windows.Foundation.DateTime ExpirationTime { get; }; + // Expiration of the Channel + Windows.Foundation.DateTime ExpirationTime { get; }; -// Unsubscribes the channel -void Close(); + // Unsubscribes the channel + void Close(); -// In-memory Event handler for Push Notifications -event Windows.Foundation.TypedEventHandler PushReceived; -} + // In-memory Event handler for Push Notifications + event Windows.Foundation.TypedEventHandler PushReceived; + } -runtimeclass PushNotificationCreateChannelResult -{ - PushNotificationCreateChannelResult( - PushNotificationChannel channel, - HRESULT extendedError, - PushNotificationChannelStatus status); + runtimeclass PushNotificationCreateChannelResult + { + PushNotificationCreateChannelResult( + PushNotificationChannel channel, + HRESULT extendedError, + PushNotificationChannelStatus status); -// The Push channel associated with the Result. Null if InProgress or completion failed -PushNotificationChannel Channel { get; }; + // The Push channel associated with the Result. Null if InProgress or completion failed + PushNotificationChannel Channel { get; }; -// More detailed error code in addition to the ChannelStatus state. -HRESULT ExtendedError{ get; }; + // More detailed error code in addition to the ChannelStatus state. + HRESULT ExtendedError{ get; }; -// The Status of the ChannelComplete operation -PushNotificationChannelStatus Status { get; }; -}; + // The Status of the ChannelComplete operation + PushNotificationChannelStatus Status { get; }; + }; -runtimeclass PushNotificationRegistrationToken -{ - PushNotificationRegistrationToken( - UInt64 cookie, - Windows.ApplicationModel.Background.BackgroundTaskRegistration taskRegistration); + runtimeclass PushNotificationRegistrationToken + { + PushNotificationRegistrationToken( + UInt64 cookie, + Windows.ApplicationModel.Background.BackgroundTaskRegistration taskRegistration); -// The cookie from CoRegisterClassObject -UInt64 Cookie{ get; }; + // The cookie from CoRegisterClassObject + UInt64 Cookie{ get; }; -// The Registration token for the Push Trigger -Windows.ApplicationModel.Background.BackgroundTaskRegistration TaskRegistration { get; }; -}; + // The Registration token for the Push Trigger + Windows.ApplicationModel.Background.BackgroundTaskRegistration TaskRegistration { get; }; + }; -static runtimeclass PushNotificationManager -{ - // Register an activator using an ActivationInfo context and return a RegistrationToken - static PushNotificationRegistrationToken RegisterActivator(PushNotificationActivationInfo details); + static runtimeclass PushNotificationManager + { + // Register an activator using an ActivationInfo context and return a RegistrationToken + static PushNotificationRegistrationToken RegisterActivator(PushNotificationActivationInfo details); -// Unregister any activator if present using a token and registrationKind -// 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 -static void UnregisterActivator(PushNotificationRegistrationToken token, PushNotificationRegistrationKind kind); + // Unregister any activator if present using a token and registrationKind + // 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 + static void UnregisterActivator(PushNotificationRegistrationToken token, PushNotificationRegistrationKind kind); -// Request a Push Channel with an encoded RemoteId from WNS. RemoteId is an AAD identifier GUID -static Windows.Foundation.IAsyncOperationWithProgress CreateChannelAsync(Guid remoteId); -}; + // Request a Push Channel with an encoded RemoteId from WNS. RemoteId is an AAD identifier GUID + static Windows.Foundation.IAsyncOperationWithProgress CreateChannelAsync(Guid remoteId); + }; } From e2810b50a3a8844ce6ac59e8bfcb647c48aa8650 Mon Sep 17 00:00:00 2001 From: Scott Darnell <20483794+aeloros@users.noreply.github.com> Date: Mon, 17 May 2021 15:30:48 -0700 Subject: [PATCH 08/53] I spoke with Paul offline and am pushing these changes to help him along this path. This change updates the PushNotifications argument parsing to utilize the encoded launch factory pattern used by the other argument types. --- dev/AppLifecycle/AppInstance.cpp | 37 +++++++++---------- dev/AppLifecycle/AppLifecycle.idl | 3 +- dev/AppLifecycle/ExtensionContract.h | 4 +- dev/AppLifecycle/FileActivatedEventArgs.h | 2 +- dev/AppLifecycle/LaunchActivatedEventArgs.h | 2 +- dev/AppLifecycle/ProtocolActivatedEventArgs.h | 2 +- dev/AppLifecycle/StartupActivatedEventArgs.h | 2 +- .../GetRawNotificationEventArgs.h | 29 ++++++--------- .../Package.appxmanifest | 2 +- .../Package.appxmanifest | 2 +- 10 files changed, 40 insertions(+), 45 deletions(-) diff --git a/dev/AppLifecycle/AppInstance.cpp b/dev/AppLifecycle/AppInstance.cpp index b17938e0cc..d3c344f24d 100644 --- a/dev/AppLifecycle/AppInstance.cpp +++ b/dev/AppLifecycle/AppInstance.cpp @@ -309,30 +309,25 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation { ExtendedActivationKind kind = ExtendedActivationKind::Launch; IInspectable data; + bool foundArgs = false; + // For packaged, try to get platform args first. if (HasIdentity()) { - - if (auto pushArgs = PushNotifications::GetRawNotificationEventArgs()) - { - data = pushArgs; - kind = ExtendedActivationKind::Push; - } - else + if (auto args = winrt::Windows::ApplicationModel::AppInstance::GetActivatedEventArgs()) { - if (auto args = winrt::Windows::ApplicationModel::AppInstance::GetActivatedEventArgs()) - { - data = args; - kind = static_cast(args.Kind()); - } + data = args; + kind = static_cast(args.Kind()); + foundArgs = true; } } - else + + // Handle all Reunion types next (both packaged and unpackaged). + std::wstring commandLine = std::wstring(GetCommandLine()); + if (!foundArgs) { - // Generate IActivatedEventArgs for non-Packaged applications. std::wstring contractId; std::wstring contractData; - auto commandLine = std::wstring(GetCommandLine()); std::tie(contractId, contractData) = ParseCommandLine(commandLine); // All specific launch types are encoded as a URI and transported as a @@ -352,14 +347,16 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation if (IsEncodedLaunch(protocolArgs.Uri())) { std::tie(kind, data) = GetEncodedLaunchActivatedEventArgs(protocolArgs); + foundArgs = true; } } + } - // Haven't set the kind yet, and so let's default to Launch. - if (kind == ExtendedActivationKind::Launch) - { - data = make(commandLine).as(); - } + // All scenarios should just be marked as Launch. + if (!foundArgs) + { + kind = ExtendedActivationKind::Launch; + data = make(commandLine).as(); } return make(kind, data); diff --git a/dev/AppLifecycle/AppLifecycle.idl b/dev/AppLifecycle/AppLifecycle.idl index 167f761450..b819fe8f67 100644 --- a/dev/AppLifecycle/AppLifecycle.idl +++ b/dev/AppLifecycle/AppLifecycle.idl @@ -50,9 +50,10 @@ namespace Microsoft.Windows.AppLifecycle PrintSupportSettingsUI, PhoneCallActivation, VpnForeground, - Push // NOTE: Values below 5000 are designated for the platform. The above list is kept in sync with // Windows.ApplicationModel.Activation.ActivationKind. + + Push = 5000, }; [experimental] diff --git a/dev/AppLifecycle/ExtensionContract.h b/dev/AppLifecycle/ExtensionContract.h index 6adb3b22c0..54b9f87974 100644 --- a/dev/AppLifecycle/ExtensionContract.h +++ b/dev/AppLifecycle/ExtensionContract.h @@ -7,6 +7,7 @@ #include "ProtocolActivatedEventArgs.h" #include "FileActivatedEventArgs.h" #include "StartupActivatedEventArgs.h" +#include "GetRawNotificationEventArgs.h" namespace winrt::Microsoft::Windows::AppLifecycle::implementation { @@ -15,7 +16,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation { ExtendedActivationKind kind; std::wstring contractId; - winrt::Windows::ApplicationModel::Activation::IActivatedEventArgs(*factory)(winrt::Windows::Foundation::Uri const& uri); + winrt::Windows::Foundation::IInspectable(*factory)(winrt::Windows::Foundation::Uri const& uri); } c_extensionMap[] = { @@ -23,6 +24,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation { ExtendedActivationKind::File, c_fileContractId, &FileActivatedEventArgs::Deserialize }, { ExtendedActivationKind::Protocol, c_protocolContractId, &ProtocolActivatedEventArgs::Deserialize }, { ExtendedActivationKind::StartupTask, c_startupTaskContractId, &StartupActivatedEventArgs::Deserialize }, + { ExtendedActivationKind::Push, c_pushContractId, &winrt::Microsoft::Windows::PushNotifications::Deserialize }, }; inline bool IsEncodedLaunch(winrt::Windows::Foundation::Uri const& uri) diff --git a/dev/AppLifecycle/FileActivatedEventArgs.h b/dev/AppLifecycle/FileActivatedEventArgs.h index 79d7d4f74d..d59b423187 100644 --- a/dev/AppLifecycle/FileActivatedEventArgs.h +++ b/dev/AppLifecycle/FileActivatedEventArgs.h @@ -44,7 +44,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation } } - static IActivatedEventArgs Deserialize(winrt::Windows::Foundation::Uri const& uri) + static winrt::Windows::Foundation::IInspectable Deserialize(winrt::Windows::Foundation::Uri const& uri) { auto query = uri.QueryParsed(); std::wstring verb = query.GetFirstValueByName(L"Verb").c_str(); diff --git a/dev/AppLifecycle/LaunchActivatedEventArgs.h b/dev/AppLifecycle/LaunchActivatedEventArgs.h index 4e7cfe49f2..ccf2bbd128 100644 --- a/dev/AppLifecycle/LaunchActivatedEventArgs.h +++ b/dev/AppLifecycle/LaunchActivatedEventArgs.h @@ -20,7 +20,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation m_kind = ActivationKind::Launch; } - static IActivatedEventArgs Deserialize(winrt::Windows::Foundation::Uri const& uri) + static winrt::Windows::Foundation::IInspectable Deserialize(winrt::Windows::Foundation::Uri const& uri) { auto query = uri.QueryParsed(); auto args = query.GetFirstValueByName(L"Arguments").c_str(); diff --git a/dev/AppLifecycle/ProtocolActivatedEventArgs.h b/dev/AppLifecycle/ProtocolActivatedEventArgs.h index 02d8b3f231..e64beb9094 100644 --- a/dev/AppLifecycle/ProtocolActivatedEventArgs.h +++ b/dev/AppLifecycle/ProtocolActivatedEventArgs.h @@ -21,7 +21,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation m_kind = ActivationKind::Protocol; } - static IActivatedEventArgs Deserialize(winrt::Windows::Foundation::Uri const& uri) + static winrt::Windows::Foundation::IInspectable Deserialize(winrt::Windows::Foundation::Uri const& uri) { auto query = uri.QueryParsed(); auto args = query.GetFirstValueByName(L"Uri").c_str(); diff --git a/dev/AppLifecycle/StartupActivatedEventArgs.h b/dev/AppLifecycle/StartupActivatedEventArgs.h index dd443d74ba..4fb39bc79e 100644 --- a/dev/AppLifecycle/StartupActivatedEventArgs.h +++ b/dev/AppLifecycle/StartupActivatedEventArgs.h @@ -20,7 +20,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation m_kind = ActivationKind::StartupTask; } - static IActivatedEventArgs Deserialize(winrt::Windows::Foundation::Uri const& uri) + static winrt::Windows::Foundation::IInspectable Deserialize(winrt::Windows::Foundation::Uri const& uri) { auto query = uri.QueryParsed(); std::wstring taskId = query.GetFirstValueByName(L"TaskId").c_str(); diff --git a/dev/PushNotifications/GetRawNotificationEventArgs.h b/dev/PushNotifications/GetRawNotificationEventArgs.h index 362f73b07b..b655da3315 100644 --- a/dev/PushNotifications/GetRawNotificationEventArgs.h +++ b/dev/PushNotifications/GetRawNotificationEventArgs.h @@ -1,31 +1,26 @@ -#include +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. +#pragma once #include "PushNotificationReceivedEventArgs.h" #include "externs.h" -using namespace winrt; -using namespace winrt::Windows::Foundation; -constexpr PCWSTR pushServerArgument = L"-ReunionPushServer"; +static PCWSTR c_pushContractId = L"Windows.Push"; namespace winrt::Microsoft::Windows::PushNotifications { - static winrt::Windows::Foundation::IInspectable GetRawNotificationEventArgs() + static winrt::Windows::Foundation::IInspectable Deserialize(winrt::Windows::Foundation::Uri const&) { winrt::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs args = nullptr; - std::wstring commandLineArgs = GetCommandLine(); - auto found = commandLineArgs.find(pushServerArgument, 0); - if (found != std::wstring::npos) { - { - auto lock = g_lock.lock(); - THROW_HR_IF_NULL_MSG(E_UNEXPECTED, g_waitHandleForArgs, "PushNotificationManager::RegisterActivator has not been called."); - } + auto lock = g_lock.lock(); + THROW_HR_IF_NULL_MSG(E_UNEXPECTED, g_waitHandleForArgs, "PushNotificationManager::RegisterActivator has not been called."); + } - if (WaitForSingleObject(g_waitHandleForArgs.get(), 1000) == WAIT_OBJECT_0) - { - auto lock = g_lock.lock(); - std::swap(args, g_activatedEventArgs); - } + if (WaitForSingleObject(g_waitHandleForArgs.get(), 1000) == WAIT_OBJECT_0) + { + auto lock = g_lock.lock(); + std::swap(args, g_activatedEventArgs); } return args; } diff --git a/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest b/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest index 0f6f091160..0ecd89debb 100644 --- a/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest +++ b/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest @@ -49,7 +49,7 @@ - + diff --git a/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest b/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest index 4ec052f6bf..7dfbf94e49 100644 --- a/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest +++ b/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest @@ -49,7 +49,7 @@ - + From 0b14a9ef0e377e3555744a8132f913e516d088e1 Mon Sep 17 00:00:00 2001 From: Scott Darnell <20483794+aeloros@users.noreply.github.com> Date: Tue, 18 May 2021 13:55:26 -0700 Subject: [PATCH 09/53] Fixed Debug builds build-break. Fixed debug tests so they run and succeed. Fixed a bunch of dependency issues in the solution that cause a lot of issues when trying to iterate on test failures. --- ProjectReunion.sln | 35 +++++++++ dev/AppLifecycle/AppInstance.cpp | 73 +++++++++++++------ test/PushNotificationTests/APITests.cpp | 23 +++--- .../PushNotificationTests.vcxproj | 14 +++- .../Package.appxmanifest | 2 +- .../Package.appxmanifest | 2 +- 6 files changed, 110 insertions(+), 39 deletions(-) diff --git a/ProjectReunion.sln b/ProjectReunion.sln index 6ef32ecf93..1b7ccf9742 100644 --- a/ProjectReunion.sln +++ b/ProjectReunion.sln @@ -125,14 +125,49 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PushNotifications", "dev\PushNotifications\PushNotifications.vcxitems", "{103C0C23-7BA8-4D44-A63C-83488E2E3A81}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PushNotificationsDemoApp", "test\TestApps\PushNotificationsDemoApp\PushNotificationsDemoApp.vcxproj", "{5B2D17FE-C371-417F-860C-3D32397C2404}" + ProjectSection(ProjectDependencies) = postProject + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + {A7391725-4EF5-438F-8DE1-645423E46955} = {A7391725-4EF5-438F-8DE1-645423E46955} + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} = {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} + {F76B776E-86F5-48C5-8FC7-D2795ECC9746} = {F76B776E-86F5-48C5-8FC7-D2795ECC9746} + {B71E818A-882E-456A-87E5-4DE4A6602B99} = {B71E818A-882E-456A-87E5-4DE4A6602B99} + EndProjectSection EndProject Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "PushNotificationsDemoPackage", "test\TestApps\PushNotificationsDemoPackage\PushNotificationsDemoPackage.wapproj", "{424A6D96-37EE-4456-8347-08AB425C8DBE}" + ProjectSection(ProjectDependencies) = postProject + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} = {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PushNotificationsTestApp", "test\TestApps\PushNotificationsTestApp\PushNotificationsTestApp.vcxproj", "{56A1D696-FEDA-4333-BF37-772EBECECB10}" + ProjectSection(ProjectDependencies) = postProject + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + {A7391725-4EF5-438F-8DE1-645423E46955} = {A7391725-4EF5-438F-8DE1-645423E46955} + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} = {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} + {F76B776E-86F5-48C5-8FC7-D2795ECC9746} = {F76B776E-86F5-48C5-8FC7-D2795ECC9746} + {B71E818A-882E-456A-87E5-4DE4A6602B99} = {B71E818A-882E-456A-87E5-4DE4A6602B99} + EndProjectSection EndProject Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "PushNotificationsTestAppPackage", "test\TestApps\PushNotificationsTestAppPackage\PushNotificationsTestAppPackage.wapproj", "{D012E4BB-F16B-472D-A26D-D449CEFA988E}" + ProjectSection(ProjectDependencies) = postProject + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + {A7391725-4EF5-438F-8DE1-645423E46955} = {A7391725-4EF5-438F-8DE1-645423E46955} + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} = {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} + {F76B776E-86F5-48C5-8FC7-D2795ECC9746} = {F76B776E-86F5-48C5-8FC7-D2795ECC9746} + {B71E818A-882E-456A-87E5-4DE4A6602B99} = {B71E818A-882E-456A-87E5-4DE4A6602B99} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PushNotificationTests", "test\PushNotificationTests\PushNotificationTests.vcxproj", "{0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}" + ProjectSection(ProjectDependencies) = postProject + {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} + {A7391725-4EF5-438F-8DE1-645423E46955} = {A7391725-4EF5-438F-8DE1-645423E46955} + {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} = {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} + {F76B776E-86F5-48C5-8FC7-D2795ECC9746} = {F76B776E-86F5-48C5-8FC7-D2795ECC9746} + {B71E818A-882E-456A-87E5-4DE4A6602B99} = {B71E818A-882E-456A-87E5-4DE4A6602B99} + {424A6D96-37EE-4456-8347-08AB425C8DBE} = {424A6D96-37EE-4456-8347-08AB425C8DBE} + {56A1D696-FEDA-4333-BF37-772EBECECB10} = {56A1D696-FEDA-4333-BF37-772EBECECB10} + {D012E4BB-F16B-472D-A26D-D449CEFA988E} = {D012E4BB-F16B-472D-A26D-D449CEFA988E} + {5B2D17FE-C371-417F-860C-3D32397C2404} = {5B2D17FE-C371-417F-860C-3D32397C2404} + EndProjectSection EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution diff --git a/dev/AppLifecycle/AppInstance.cpp b/dev/AppLifecycle/AppInstance.cpp index d3c344f24d..8c568b7744 100644 --- a/dev/AppLifecycle/AppInstance.cpp +++ b/dev/AppLifecycle/AppInstance.cpp @@ -34,22 +34,34 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation // Push past the '----' commandline argument prefix. argsStart += 4; - // We explicitly use find_first_of here, so that the resulting data may contain : as a valid character. - auto argsEnd = commandLine.find_first_of(L":", argsStart); + auto argsEnd = commandLine.find_first_of(L" ", argsStart); + + std::wstring argument; if (argsEnd == std::wstring::npos) { - return { L"", L"" }; + argument = commandLine.substr(argsStart); } + else + { + if (argsStart > argsEnd) + { + throw std::invalid_argument("commandLine"); + } - if (argsStart > argsEnd) + argument = commandLine.substr(argsStart, (argsEnd - argsStart)); + } + + // We explicitly use find_first_of here, so that the resulting data may contain : as a valid character. + auto argsDelim = argument.find_first_of(L":", argsStart); + if (argsDelim == std::wstring::npos) { - throw std::overflow_error("commandLine"); + return { argument, L"" }; } - auto argsLength = argsEnd - argsStart; - auto dataStart = argsEnd + 1; + auto argsLength = argsDelim - argsStart; + auto dataStart = argsDelim + 1; - return { commandLine.substr(argsStart, argsLength), commandLine.substr(dataStart) }; + return { argument.substr(argsStart, argsLength), argument.substr(dataStart) }; } std::tuple GetEncodedLaunchActivatedEventArgs(IProtocolActivatedEventArgs const& args) @@ -326,27 +338,42 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation std::wstring commandLine = std::wstring(GetCommandLine()); if (!foundArgs) { - std::wstring contractId; + std::wstring contractArgument; std::wstring contractData; - std::tie(contractId, contractData) = ParseCommandLine(commandLine); + + std::tie(contractArgument, contractData) = ParseCommandLine(commandLine); // All specific launch types are encoded as a URI and transported as a // protocol, except the catch-all LaunchActivatedEventArgs case. - if (!contractId.empty() && (CompareStringOrdinal(contractId.c_str(), -1, c_protocolArgumentString, -1, TRUE) == CSTR_EQUAL)) + if (!contractArgument.empty()) { - kind = ExtendedActivationKind::Protocol; - auto args = make(contractData); - data = args.as(); - - // Encoded launch is a protocol launch where the argument data is - // encapsulated in the Uri Query data. We handle that here and - // try to return the correct IActivatedEventArgs type that is - // encoded in the data rather than the IProtocolActivatedEventArgs - // itself. - auto protocolArgs = args.as(); - if (IsEncodedLaunch(protocolArgs.Uri())) + if (contractData.empty()) { - std::tie(kind, data) = GetEncodedLaunchActivatedEventArgs(protocolArgs); + // If the contractData is empty, handle any aliased encoded launches. + if (CompareStringOrdinal(contractArgument.c_str(), -1, L"ReunionPushServer", -1, TRUE) == CSTR_EQUAL) + { + contractData = GenerateEncodedLaunchUri(L"App", c_pushContractId); + contractArgument = c_protocolArgumentString; + } + } + + if (CompareStringOrdinal(contractArgument.c_str(), -1, c_protocolArgumentString, -1, TRUE) == CSTR_EQUAL) + { + kind = ExtendedActivationKind::Protocol; + auto args = make(contractData); + data = args.as(); + + // Encoded launch is a protocol launch where the argument data is + // encapsulated in the Uri Query data. We handle that here and + // try to return the correct IActivatedEventArgs type that is + // encoded in the data rather than the IProtocolActivatedEventArgs + // itself. + auto protocolArgs = args.as(); + if (IsEncodedLaunch(protocolArgs.Uri())) + { + std::tie(kind, data) = GetEncodedLaunchActivatedEventArgs(protocolArgs); + } + foundArgs = true; } } diff --git a/test/PushNotificationTests/APITests.cpp b/test/PushNotificationTests/APITests.cpp index a76544d058..4ba1b0e979 100644 --- a/test/PushNotificationTests/APITests.cpp +++ b/test/PushNotificationTests/APITests.cpp @@ -18,9 +18,6 @@ using namespace winrt::Windows::Management::Deployment; using namespace winrt::Windows::Storage; using namespace winrt::Windows::System; - -// TODO: Write Register/Unregister tests that utilize the Assoc APIs to validate results. - namespace Test::PushNotifications { class APITests @@ -28,24 +25,31 @@ namespace Test::PushNotifications private: wil::unique_event m_failed; - const std::wstring c_testPackageFile = g_deploymentDir + L"PushNotificationsTestAppPackage.msixbundle"; - const std::wstring c_testPackageCertFile = g_deploymentDir + L"PushNotificationsTestAppPackage.cer"; - const std::wstring c_testPackageFullName = L"PushNotificationsTestAppPackage_1.0.0.0_x64__8wekyb3d8bbwe"; + const std::wstring c_testPackageFile = g_deploymentDir + L"PushNotificationsTestAppPackage.msix"; + const std::wstring c_testPackageFullName = L"PushNotificationsTestAppPackage_1.0.0.0_" PROJECTREUNION_TEST_PACKAGE_DDLM_ARCHITECTURE L"__8wekyb3d8bbwe"; + const std::wstring c_testVCLibsPackageFile = g_deploymentDir + L"VCLibs.appx"; public: BEGIN_TEST_CLASS(APITests) TEST_CLASS_PROPERTY(L"Description", L"Project Reunion Push Notifications test") - TEST_CLASS_PROPERTY(L"IsolationLevel", L"Method") TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA") - TEST_CLASS_PROPERTY(L"RunFixtureAs:Class", L"ElevatedUser") + TEST_CLASS_PROPERTY(L"RunAs:Class", L"RestrictedUser") END_TEST_CLASS() TEST_CLASS_SETUP(ClassInit) { + try + { + InstallPackage(c_testVCLibsPackageFile); + } + catch (...) + { + return false; + } + TP::AddPackage_ProjectReunionFramework(); try { - RunCertUtil(c_testPackageCertFile, false); InstallPackage(c_testPackageFile); } catch (...) @@ -62,7 +66,6 @@ namespace Test::PushNotifications try { UninstallPackage(c_testPackageFullName); - RunCertUtil(c_testPackageCertFile, true); } catch (...) { diff --git a/test/PushNotificationTests/PushNotificationTests.vcxproj b/test/PushNotificationTests/PushNotificationTests.vcxproj index b00566483d..6e365ea245 100644 --- a/test/PushNotificationTests/PushNotificationTests.vcxproj +++ b/test/PushNotificationTests/PushNotificationTests.vcxproj @@ -173,12 +173,18 @@ - - _Debug + + .Debug + _Debug + + $(AppxPackageDir)\PushNotificationsTestAppPackage_1.0.0.0_$(PlatformTarget)$(TestPkgDebugConfigName)_Test + $(OutDir)\PushNotificationsTestAppPackage\AppPackages\PushNotificationsTestAppPackage_1.0.0.0$(TestPkgDebugConfigName)_Test + $(TestPkgOutputPath)\PushNotificationsTestAppPackage_1.0.0.0_$(PlatformTarget)$(TestPkgDebugConfigName).msix + $(TestPkgOutputPath)\PushNotificationsTestAppPackage_1.0.0.0_$(PlatformTarget)$(TestPkgDebugConfigName).msixbundle - - + + diff --git a/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest b/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest index 0ecd89debb..e91ef0d8a2 100644 --- a/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest +++ b/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest @@ -49,7 +49,7 @@ - + diff --git a/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest b/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest index 7dfbf94e49..c811ee0e06 100644 --- a/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest +++ b/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest @@ -49,7 +49,7 @@ - + From 6dab535831bdcd0ec26d7dcf6de18700e6f2d5c8 Mon Sep 17 00:00:00 2001 From: Sharath Manchala <10109130+sharath2727@users.noreply.github.com> Date: Tue, 18 May 2021 10:56:00 -0700 Subject: [PATCH 10/53] Address comments for channel request --- .../PushNotificationManager.cpp | 2 +- dev/PushNotifications/PushNotifications.idl | 12 +- test/PushNotificationTests/APITests.cpp | 6 +- .../PushNotificationsTestApp/main.cpp | 331 ++++++++---------- 4 files changed, 153 insertions(+), 198 deletions(-) diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp index 771d9a8afc..4b7ec31cad 100644 --- a/dev/PushNotifications/PushNotificationManager.cpp +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -116,7 +116,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation PushNotificationChannelStatus status = PushNotificationChannelStatus::InProgress; PushNotificationCreateChannelStatus - channelStatus = { channelRequestResult, status, retryCount }; + channelStatus = { status, channelRequestResult, retryCount }; progress(channelStatus); diff --git a/dev/PushNotifications/PushNotifications.idl b/dev/PushNotifications/PushNotifications.idl index a841fd41fc..ee32e00568 100644 --- a/dev/PushNotifications/PushNotifications.idl +++ b/dev/PushNotifications/PushNotifications.idl @@ -61,12 +61,12 @@ namespace Microsoft.Windows.PushNotifications // The PushNotificationChannel Progress result struct PushNotificationCreateChannelStatus { - // The last extended error we failed Channel requests on that caused the inprogress retry status. S_OK if this is just progress status. - HRESULT extendedError; - // Either InProgress or InProgressRetry status PushNotificationChannelStatus status; + // The last extended error we failed Channel requests on that caused the inprogress retry status. E_PENDING if this is just progress status. + HRESULT extendedError; + // Total Retries so far UInt32 retryCount; }; @@ -84,7 +84,7 @@ namespace Microsoft.Windows.PushNotifications // Unsubscribes the channel void Close(); - // In-memory Event handler for Push Notifications + // Event handler for Push Notifications event Windows.Foundation.TypedEventHandler PushReceived; } @@ -95,7 +95,7 @@ namespace Microsoft.Windows.PushNotifications HRESULT extendedError, PushNotificationChannelStatus status); - // The Push channel associated with the Result. Null if InProgress or completion failed + // The Push channel associated with the Result. Valid only if status is CompletedSuccess. PushNotificationChannel Channel { get; }; // More detailed error code in addition to the ChannelStatus state. @@ -128,7 +128,7 @@ namespace Microsoft.Windows.PushNotifications // 2) If kind = ComActivator is specified, the Project Reunion Background Task component will no longer act as an InProc COM Server static void UnregisterActivator(PushNotificationRegistrationToken token, PushNotificationRegistrationKind kind); - // Request a Push Channel with an encoded RemoteId from WNS. RemoteId is an AAD identifier GUID + // Request a Push Channel using an encoded AAD GUID identifier from WNS. static Windows.Foundation.IAsyncOperationWithProgress CreateChannelAsync(Guid remoteId); }; } diff --git a/test/PushNotificationTests/APITests.cpp b/test/PushNotificationTests/APITests.cpp index 4ba1b0e979..d5cf728ab7 100644 --- a/test/PushNotificationTests/APITests.cpp +++ b/test/PushNotificationTests/APITests.cpp @@ -25,9 +25,9 @@ namespace Test::PushNotifications private: wil::unique_event m_failed; - const std::wstring c_testPackageFile = g_deploymentDir + L"PushNotificationsTestAppPackage.msix"; - const std::wstring c_testPackageFullName = L"PushNotificationsTestAppPackage_1.0.0.0_" PROJECTREUNION_TEST_PACKAGE_DDLM_ARCHITECTURE L"__8wekyb3d8bbwe"; - const std::wstring c_testVCLibsPackageFile = g_deploymentDir + L"VCLibs.appx"; + const std::wstring c_testPackageFile = g_deploymentDir + L"PushNotificationsTestAppPackage_1.0.0.0_x64.msixbundle"; + const std::wstring c_testPackageCertFile = g_deploymentDir + L"PushNotificationsTestAppPackage_1.0.0.0_x64.cer"; + const std::wstring c_testPackageFullName = L"PushNotificationsTestAppPackage_1.0.0.0_x64__8wekyb3d8bbwe"; public: BEGIN_TEST_CLASS(APITests) diff --git a/test/TestApps/PushNotificationsTestApp/main.cpp b/test/TestApps/PushNotificationsTestApp/main.cpp index f3d9cf75d0..27f016eae0 100644 --- a/test/TestApps/PushNotificationsTestApp/main.cpp +++ b/test/TestApps/PushNotificationsTestApp/main.cpp @@ -48,7 +48,7 @@ bool ChannelRequestUsingNullRemoteId() try { - auto channelOperation = PushNotificationManager::CreateChannelAsync(GUID_NULL).get(); + auto channelOperation = PushNotificationManager::CreateChannelAsync(winrt::guid()).get(); } catch (...) { @@ -61,38 +61,27 @@ bool ChannelRequestUsingNullRemoteId() bool ChannelRequestUsingRemoteId() { - wil::unique_handle channelEvent = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); auto channelOperationResult = S_OK; auto channelOperation = PushNotificationManager::CreateChannelAsync(remoteId1); - // Setup the completed event handler - channelOperation.Completed( - [&channelEvent, &channelOperationResult]( - IAsyncOperationWithProgress const& sender, - AsyncStatus const /* asyncStatus */) - { - auto result = sender.GetResults(); - if (result.Status() == PushNotificationChannelStatus::CompletedSuccess) - { - result.Channel().Close(); // Avoids using cached channel everytime the test runs - } - else if (result.Status() == PushNotificationChannelStatus::CompletedFailure) - { - channelOperationResult = result.ExtendedError(); - } - - SetEvent(channelEvent.get()); - }); - - // The maximum amount of time it takes for channel request to be obtained - 16mins - if (WAIT_OBJECT_0 != WaitForSingleObject(channelEvent.get(), 960000 /* milliseconds */)) + switch (channelOperation.wait_for(std::chrono::seconds(960))) { - channelOperation.Cancel(); - channelOperationResult = ERROR_TIMEOUT; - } - else + case AsyncStatus::Completed: { - channelOperation.Close(); // Do not call getresults after this + auto channelResult = channelOperation.GetResults(); + if (channelResult.Status() == PushNotificationChannelStatus::CompletedSuccess) + { + channelResult.Channel().Close(); // Avoids using cached channel everytime the test runs + } + else if (channelResult.Status() == PushNotificationChannelStatus::CompletedFailure) + { + channelOperationResult = channelResult.ExtendedError(); + } + break; + } + default: + channelOperationResult = ERROR_TIMEOUT; + break; } return (channelOperationResult == S_OK); @@ -100,61 +89,53 @@ bool ChannelRequestUsingRemoteId() bool MultipleChannelRequestUsingSameRemoteId() { - wil::unique_handle channelEvent1 = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); - wil::unique_handle channelEvent2 = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); - - auto channelOperationResult2 = S_OK; - + auto channelOperationResult1 = S_OK; auto channelOperation1 = PushNotificationManager::CreateChannelAsync(remoteId1); - channelOperation1.Completed( - [&channelEvent1]( - IAsyncOperationWithProgress const& sender, - AsyncStatus const /* asyncStatus */) - { - auto result = sender.GetResults(); - if (result.Status() == PushNotificationChannelStatus::CompletedSuccess) - { - result.Channel().Close(); // Avoids using cached channel everytime the test runs - } - else if (result.Status() == PushNotificationChannelStatus::CompletedFailure) - { - } - - SetEvent(channelEvent1.get()); - }); + auto channelOperationResult2 = S_OK; auto channelOperation2 = PushNotificationManager::CreateChannelAsync(remoteId1); - channelOperation2.Completed( - [&channelEvent2, &channelOperationResult2]( - IAsyncOperationWithProgress const& sender, - AsyncStatus const /* asyncStatus */) - { - auto result = sender.GetResults(); - if (result.Status() == PushNotificationChannelStatus::CompletedSuccess) - { - result.Channel().Close(); // Avoids using cached channel everytime the test runs - } - else if (result.Status() == PushNotificationChannelStatus::CompletedFailure) - { - channelOperationResult2 = result.ExtendedError(); - } - - SetEvent(channelEvent2.get()); - }); - - // The maximum amount of time it takes for channel request to be obtained - 16mins - if (WAIT_OBJECT_0 != WaitForSingleObject(channelEvent2.get(), 960000 /* milliseconds */)) + switch (channelOperation2.wait_for(std::chrono::seconds(960))) { - channelOperation2.Cancel(); + case AsyncStatus::Completed: + { + auto channelResult2 = channelOperation2.GetResults(); + if (channelResult2.Status() == PushNotificationChannelStatus::CompletedSuccess) + { + channelResult2.Channel().Close(); // Avoids using cached channel everytime the test runs + } + else if (channelResult2.Status() == PushNotificationChannelStatus::CompletedFailure) + { + channelOperationResult2 = channelResult2.ExtendedError(); + } + break; + } + + default: channelOperationResult2 = ERROR_TIMEOUT; + break; } - // The maximum amount of time it takes for channel request to be obtained - 16mins - if (WAIT_OBJECT_0 != WaitForSingleObject(channelEvent1.get(), 960000 /* milliseconds */)) + switch (channelOperation1.wait_for(std::chrono::seconds(960))) { - channelOperation1.Cancel(); + case AsyncStatus::Completed: + { + auto channelResult1 = channelOperation1.GetResults(); + if (channelResult1.Status() == PushNotificationChannelStatus::CompletedSuccess) + { + channelResult1.Channel().Close(); // Avoids using cached channel everytime the test runs + } + else if (channelResult1.Status() == PushNotificationChannelStatus::CompletedFailure) + { + channelOperationResult1 = channelResult1.ExtendedError(); + } + break; + } + + default: + channelOperationResult1 = ERROR_TIMEOUT; + break; } return (channelOperationResult2 == WPN_E_OUTSTANDING_CHANNEL_REQUEST); @@ -162,61 +143,52 @@ bool MultipleChannelRequestUsingSameRemoteId() bool MultipleChannelRequestUsingMultipleRemoteId() { - wil::unique_handle channelEvent1 = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); - wil::unique_handle channelEvent2 = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); - - auto channelOperationResult2 = S_OK; - + auto channelOperationResult1 = S_OK; auto channelOperation1 = PushNotificationManager::CreateChannelAsync(remoteId1); - channelOperation1.Completed( - [&channelEvent1]( - IAsyncOperationWithProgress const& sender, - AsyncStatus const /* asyncStatus */) - { - auto result = sender.GetResults(); - if (result.Status() == PushNotificationChannelStatus::CompletedSuccess) - { - result.Channel().Close(); - } - else if (result.Status() == PushNotificationChannelStatus::CompletedFailure) - { - } - - SetEvent(channelEvent1.get()); - }); + auto channelOperationResult2 = S_OK; auto channelOperation2 = PushNotificationManager::CreateChannelAsync(remoteId2); - channelOperation2.Completed( - [&channelEvent2, &channelOperationResult2]( - IAsyncOperationWithProgress const& sender, - AsyncStatus const /* asyncStatus */) - { - auto result = sender.GetResults(); - if (result.Status() == PushNotificationChannelStatus::CompletedSuccess) - { - result.Channel().Close(); - } - else if (result.Status() == PushNotificationChannelStatus::CompletedFailure) - { - channelOperationResult2 = result.ExtendedError(); - } - - SetEvent(channelEvent2.get()); - }); - - // The maximum amount of time it takes for channel request to be obtained - 16mins - if (WAIT_OBJECT_0 != WaitForSingleObject(channelEvent2.get(), 960000 /* milliseconds */)) + switch (channelOperation2.wait_for(std::chrono::seconds(960))) + { + case AsyncStatus::Completed: { - channelOperation2.Cancel(); + auto channelResult2 = channelOperation2.GetResults(); + if (channelResult2.Status() == PushNotificationChannelStatus::CompletedSuccess) + { + channelResult2.Channel().Close(); // Avoids using cached channel everytime the test runs + } + else if (channelResult2.Status() == PushNotificationChannelStatus::CompletedFailure) + { + channelOperationResult2 = channelResult2.ExtendedError(); + } + break; + } + + default: channelOperationResult2 = ERROR_TIMEOUT; + break; } - // The maximum amount of time it takes for channel request to be obtained - 16mins - if (WAIT_OBJECT_0 != WaitForSingleObject(channelEvent1.get(), 960000 /* milliseconds */)) + switch (channelOperation1.wait_for(std::chrono::seconds(960))) + { + case AsyncStatus::Completed: { - channelOperation1.Cancel(); + auto channelResult1 = channelOperation1.GetResults(); + if (channelResult1.Status() == PushNotificationChannelStatus::CompletedSuccess) + { + channelResult1.Channel().Close(); // Avoids using cached channel everytime the test runs + } + else if (channelResult1.Status() == PushNotificationChannelStatus::CompletedFailure) + { + channelOperationResult1 = channelResult1.ExtendedError(); + } + break; + } + default: + channelOperationResult1 = ERROR_TIMEOUT; + break; } return (channelOperationResult2 == WPN_E_OUTSTANDING_CHANNEL_REQUEST); @@ -224,92 +196,75 @@ bool MultipleChannelRequestUsingMultipleRemoteId() bool ThreeChannelRequestUsingSameRemoteId() { - wil::unique_handle channelEvent1 = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + auto channelOperationResult1 = S_OK; + auto channelOperation1 = PushNotificationManager::CreateChannelAsync(remoteId1); - wil::unique_handle channelEvent2 = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); auto channelOperationResult2 = S_OK; - wil::unique_handle channelEvent3 = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); - auto channelOperationResult3 = S_OK; - - auto channelOperation1 = PushNotificationManager::CreateChannelAsync(remoteId1); + auto channelOperation2 = PushNotificationManager::CreateChannelAsync(remoteId1); - channelOperation1.Completed( - [&channelEvent1]( - IAsyncOperationWithProgress const& sender, - AsyncStatus const /* asyncStatus */) - { - auto result = sender.GetResults(); - if (result.Status() == PushNotificationChannelStatus::CompletedSuccess) - { - result.Channel().Close(); - } - else if (result.Status() == PushNotificationChannelStatus::CompletedFailure) - { - } - - SetEvent(channelEvent1.get()); - }); + auto channelOperationResult3 = S_OK; - auto channelOperation2 = PushNotificationManager::CreateChannelAsync(remoteId2); + auto channelOperation3 = PushNotificationManager::CreateChannelAsync(remoteId1); - channelOperation2.Completed( - [&channelEvent2, &channelOperationResult2]( - IAsyncOperationWithProgress const& sender, - AsyncStatus const /* asyncStatus */) + switch (channelOperation2.wait_for(std::chrono::seconds(960))) + { + case AsyncStatus::Completed: + { + auto channelResult2 = channelOperation2.GetResults(); + if (channelResult2.Status() == PushNotificationChannelStatus::CompletedSuccess) { - auto result = sender.GetResults(); - if (result.Status() == PushNotificationChannelStatus::CompletedSuccess) - { - result.Channel().Close(); - } - else if (result.Status() == PushNotificationChannelStatus::CompletedFailure) - { - channelOperationResult2 = result.ExtendedError(); - } - - SetEvent(channelEvent2.get()); - }); - - - auto channelOperation3 = PushNotificationManager::CreateChannelAsync(remoteId3); - - channelOperation3.Completed( - [&channelEvent3, &channelOperationResult3]( - IAsyncOperationWithProgress const& sender, - AsyncStatus const /* asyncStatus */) + channelResult2.Channel().Close(); // Avoids using cached channel everytime the test runs + } + else if (channelResult2.Status() == PushNotificationChannelStatus::CompletedFailure) { - auto result = sender.GetResults(); - if (result.Status() == PushNotificationChannelStatus::CompletedSuccess) - { - result.Channel().Close(); - } - else if (result.Status() == PushNotificationChannelStatus::CompletedFailure) - { - channelOperationResult3 = result.ExtendedError(); - } - - SetEvent(channelEvent3.get()); - }); - - // The maximum amount of time it takes for channel request to be obtained - 16mins - if (WAIT_OBJECT_0 != WaitForSingleObject(channelEvent2.get(), 960000 /* milliseconds */)) - { - channelOperation2.Cancel(); + channelOperationResult2 = channelResult2.ExtendedError(); + } + break; + } + default: channelOperationResult2 = ERROR_TIMEOUT; + break; } - // The maximum amount of time it takes for channel request to be obtained - 16mins - if (WAIT_OBJECT_0 != WaitForSingleObject(channelEvent3.get(), 960000 /* milliseconds */)) + switch (channelOperation3.wait_for(std::chrono::seconds(960))) + { + case AsyncStatus::Completed: { - channelOperation3.Cancel(); + auto channelResult3 = channelOperation3.GetResults(); + if (channelResult3.Status() == PushNotificationChannelStatus::CompletedSuccess) + { + channelResult3.Channel().Close(); // Avoids using cached channel everytime the test runs + } + else if (channelResult3.Status() == PushNotificationChannelStatus::CompletedFailure) + { + channelOperationResult3 = channelResult3.ExtendedError(); + } + break; + } + default: channelOperationResult3 = ERROR_TIMEOUT; + break; } - // The maximum amount of time it takes for channel request to be obtained - 16mins - if (WAIT_OBJECT_0 != WaitForSingleObject(channelEvent1.get(), 960000 /* milliseconds */)) + switch (channelOperation1.wait_for(std::chrono::seconds(960))) { - channelOperation1.Cancel(); + case AsyncStatus::Completed: + { + auto channelResult1 = channelOperation1.GetResults(); + if (channelResult1.Status() == PushNotificationChannelStatus::CompletedSuccess) + { + channelResult1.Channel().Close(); // Avoids using cached channel everytime the test runs + } + else if (channelResult1.Status() == PushNotificationChannelStatus::CompletedFailure) + { + channelOperationResult1 = channelResult1.ExtendedError(); + } + break; + } + default: + channelOperationResult1 = ERROR_TIMEOUT; + break; } return ((channelOperationResult2 == WPN_E_OUTSTANDING_CHANNEL_REQUEST) && (channelOperationResult3 == WPN_E_OUTSTANDING_CHANNEL_REQUEST)); From 0ec5bfb945a8b0a25faef46e6e8aab70163ac86d Mon Sep 17 00:00:00 2001 From: Sharath Manchala <10109130+sharath2727@users.noreply.github.com> Date: Tue, 18 May 2021 11:43:49 -0700 Subject: [PATCH 11/53] Add experimental tag to the runtimeclasses --- dev/PushNotifications/PushNotifications.idl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dev/PushNotifications/PushNotifications.idl b/dev/PushNotifications/PushNotifications.idl index ee32e00568..81b264bc4c 100644 --- a/dev/PushNotifications/PushNotifications.idl +++ b/dev/PushNotifications/PushNotifications.idl @@ -3,6 +3,7 @@ namespace Microsoft.Windows.PushNotifications { + [experimental] // Event args for the Push payload. runtimeclass PushNotificationReceivedEventArgs { @@ -32,6 +33,7 @@ namespace Microsoft.Windows.PushNotifications ComActivator = 0x2, // Registers the Project Reunion Background Task component as an InProc COM server }; + [experimental] // An abstraction over the activation Registration flow runtimeclass PushNotificationActivationInfo { @@ -71,6 +73,7 @@ namespace Microsoft.Windows.PushNotifications UInt32 retryCount; }; + [experimental] runtimeclass PushNotificationChannel { PushNotificationChannel(Windows.Networking.PushNotifications.PushNotificationChannel channel); @@ -88,6 +91,7 @@ namespace Microsoft.Windows.PushNotifications event Windows.Foundation.TypedEventHandler PushReceived; } + [experimental] runtimeclass PushNotificationCreateChannelResult { PushNotificationCreateChannelResult( @@ -105,6 +109,7 @@ namespace Microsoft.Windows.PushNotifications PushNotificationChannelStatus Status { get; }; }; + [experimental] runtimeclass PushNotificationRegistrationToken { PushNotificationRegistrationToken( @@ -118,6 +123,7 @@ namespace Microsoft.Windows.PushNotifications Windows.ApplicationModel.Background.BackgroundTaskRegistration TaskRegistration { get; }; }; + [experimental] static runtimeclass PushNotificationManager { // Register an activator using an ActivationInfo context and return a RegistrationToken From 032b8d51601962ce671c62935887b83182485db9 Mon Sep 17 00:00:00 2001 From: Scott Darnell <20483794+aeloros@users.noreply.github.com> Date: Tue, 18 May 2021 14:23:59 -0700 Subject: [PATCH 12/53] Fixed a bug in my last change. --- dev/AppLifecycle/AppInstance.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/dev/AppLifecycle/AppInstance.cpp b/dev/AppLifecycle/AppInstance.cpp index 8c568b7744..f84ddef151 100644 --- a/dev/AppLifecycle/AppInstance.cpp +++ b/dev/AppLifecycle/AppInstance.cpp @@ -36,6 +36,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation auto argsEnd = commandLine.find_first_of(L" ", argsStart); + // Separate the argument from any behind it on the command-line. std::wstring argument; if (argsEnd == std::wstring::npos) { @@ -52,16 +53,13 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation } // We explicitly use find_first_of here, so that the resulting data may contain : as a valid character. - auto argsDelim = argument.find_first_of(L":", argsStart); + auto argsDelim = argument.find_first_of(L":"); if (argsDelim == std::wstring::npos) { return { argument, L"" }; } - auto argsLength = argsDelim - argsStart; - auto dataStart = argsDelim + 1; - - return { argument.substr(argsStart, argsLength), argument.substr(dataStart) }; + return { argument.substr(0, argsDelim), argument.substr(argsDelim + 1) }; } std::tuple GetEncodedLaunchActivatedEventArgs(IProtocolActivatedEventArgs const& args) From 8d7b143bc87b44353bf51f70fa4eddaf620c6013 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Tue, 18 May 2021 17:50:20 -0700 Subject: [PATCH 13/53] Removed static handlers and a fixed a few nits --- .../PushNotificationChannel.cpp | 37 ++------- .../PushNotificationChannel.h | 2 +- .../PushNotificationCreateChannelResult.cpp | 9 ++- .../PushNotificationCreateChannelResult.h | 8 +- .../PushNotificationManager.cpp | 21 +++-- .../PushNotificationManager.h | 2 +- .../PushNotificationReceivedEventArgs.cpp | 44 +++++----- .../PushNotificationsDemoApp/main.cpp | 80 +++++++++++-------- 8 files changed, 98 insertions(+), 105 deletions(-) diff --git a/dev/PushNotifications/PushNotificationChannel.cpp b/dev/PushNotifications/PushNotificationChannel.cpp index 4b10c84a3c..ac0b9abc8c 100644 --- a/dev/PushNotifications/PushNotificationChannel.cpp +++ b/dev/PushNotifications/PushNotificationChannel.cpp @@ -12,57 +12,32 @@ namespace winrt namespace winrt::Microsoft::Windows::PushNotifications::implementation { - // Need static handler/lock to keep alive upon channel request completion - winrt::TypedEventHandler< - Microsoft::Windows::PushNotifications::PushNotificationChannel, - Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs> s_typedEventHandler; - wil::srwlock s_lock; + PushNotificationChannel::PushNotificationChannel(winrt::PushNotificationChannel const& channel): m_channel(channel) {} - PushNotificationChannel::PushNotificationChannel(winrt::PushNotificationChannel const& channel) - { - m_channel = channel; - } winrt::Uri PushNotificationChannel::Uri() { - auto lock = s_lock.lock_shared(); return winrt::Uri{ m_channel.Uri() }; } winrt::DateTime PushNotificationChannel::ExpirationTime() { - auto lock = s_lock.lock_shared(); return m_channel.ExpirationTime(); } void PushNotificationChannel::Close() { - auto lock = s_lock.lock_shared(); m_channel.Close(); } winrt::event_token PushNotificationChannel::PushReceived(winrt::TypedEventHandler const& handler) { - - winrt::TypedEventHandler< - winrt::PushNotificationChannel, - winrt::PushNotificationReceivedEventArgs> typedEventHandler - ([&]( - winrt::PushNotificationChannel channel, - winrt::PushNotificationReceivedEventArgs args) - { - PushNotificationReceivedEventArgs pushArgs = - PushNotificationReceivedEventArgs::CreateFromPushNotificationReceivedEventArgs(args); - auto lock = s_lock.lock_shared(); - s_typedEventHandler(*this, pushArgs); - }); - - auto lock = s_lock.lock_exclusive(); - s_typedEventHandler = handler; - return m_channel.PushNotificationReceived(typedEventHandler); + return m_channel.PushNotificationReceived([weak_self = get_weak(), handler](auto&&, auto&& args) + { + auto strong = weak_self.get(); + if (strong) handler(*strong, PushNotificationReceivedEventArgs::CreateFromPushNotificationReceivedEventArgs(args)); + }); } void PushNotificationChannel::PushReceived(winrt::event_token const& token) noexcept { - auto lock = s_lock.lock_exclusive(); - s_typedEventHandler = nullptr; m_channel.PushNotificationReceived(token); } } diff --git a/dev/PushNotifications/PushNotificationChannel.h b/dev/PushNotifications/PushNotificationChannel.h index 8a53db7db2..062ab52ea8 100644 --- a/dev/PushNotifications/PushNotificationChannel.h +++ b/dev/PushNotifications/PushNotificationChannel.h @@ -16,7 +16,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation void PushReceived(winrt::event_token const& token) noexcept; private: - winrt::Windows::Networking::PushNotifications::PushNotificationChannel m_channel{ nullptr }; + const winrt::Windows::Networking::PushNotifications::PushNotificationChannel m_channel{ nullptr }; }; } diff --git a/dev/PushNotifications/PushNotificationCreateChannelResult.cpp b/dev/PushNotifications/PushNotificationCreateChannelResult.cpp index 1d96b1426c..d9465b0a55 100644 --- a/dev/PushNotifications/PushNotificationCreateChannelResult.cpp +++ b/dev/PushNotifications/PushNotificationCreateChannelResult.cpp @@ -4,12 +4,13 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { - PushNotificationCreateChannelResult::PushNotificationCreateChannelResult(PushNotificationChannel const& channel, winrt::hresult const& extendedError, PushNotificationChannelStatus const& status) + PushNotificationCreateChannelResult::PushNotificationCreateChannelResult(PushNotificationChannel const& channel, winrt::hresult const& extendedError, PushNotificationChannelStatus const& status): + m_channel(channel), + m_extendedError(extendedError), + m_status(status) { - m_channel = channel; - m_extendedError = extendedError; - m_status = status; } + PushNotificationChannel PushNotificationCreateChannelResult::Channel() { return m_channel; diff --git a/dev/PushNotifications/PushNotificationCreateChannelResult.h b/dev/PushNotifications/PushNotificationCreateChannelResult.h index be50222ef8..b9ba9ef732 100644 --- a/dev/PushNotifications/PushNotificationCreateChannelResult.h +++ b/dev/PushNotifications/PushNotificationCreateChannelResult.h @@ -5,17 +5,15 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { struct PushNotificationCreateChannelResult : PushNotificationCreateChannelResultT { - PushNotificationCreateChannelResult() = default; - PushNotificationCreateChannelResult(Microsoft::Windows::PushNotifications::PushNotificationChannel const& channel, hresult const& extendedError, Microsoft::Windows::PushNotifications::PushNotificationChannelStatus const& status); Microsoft::Windows::PushNotifications::PushNotificationChannel Channel(); winrt::hresult ExtendedError(); Microsoft::Windows::PushNotifications::PushNotificationChannelStatus Status(); private: - Microsoft::Windows::PushNotifications::PushNotificationChannel m_channel{ nullptr }; - winrt::hresult m_extendedError; - Microsoft::Windows::PushNotifications::PushNotificationChannelStatus m_status; + const Microsoft::Windows::PushNotifications::PushNotificationChannel m_channel{ nullptr }; + const winrt::hresult m_extendedError; + const Microsoft::Windows::PushNotifications::PushNotificationChannelStatus m_status; }; } namespace winrt::Microsoft::Windows::PushNotifications::factory_implementation diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp index 4b7ec31cad..a59aad6538 100644 --- a/dev/PushNotifications/PushNotificationManager.cpp +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -37,7 +37,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation const HRESULT WNP_E_RECONNECTING = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x880403E9L); const HRESULT WNP_E_BIND_USER_BUSY = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x880403FEL); - bool PushNotificationManager::isChannelRequestRetryable(const hresult& hr) + bool PushNotificationManager::IsChannelRequestRetryable(const hresult& hr) { switch (hr) { @@ -137,7 +137,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation auto channelRequestException = hresult_error(to_hresult(), take_ownership_from_abi); - if ((backOffTimeInSeconds <= c_maxBackoffSeconds) && isChannelRequestRetryable(channelRequestException.code())) + if ((backOffTimeInSeconds <= c_maxBackoffSeconds) && IsChannelRequestRetryable(channelRequestException.code())) { channelStatus.extendedError = channelRequestException.code(); channelStatus.status = PushNotificationChannelStatus::InProgressRetry; @@ -182,8 +182,11 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation PushNotificationRegistrationToken PushNotificationManager::RegisterActivator(PushNotificationActivationInfo const& details) { winrt::guid taskClsid = details.TaskClsid(); + THROW_HR_IF(E_INVALIDARG, taskClsid == winrt::guid(GUID_NULL)); + DWORD cookie = 0; BackgroundTaskRegistration registeredTask = nullptr; + BackgroundTaskBuilder builder = nullptr; if (WI_IsFlagSet(details.Kind(), PushNotificationRegistrationKind::PushTrigger)) { @@ -192,7 +195,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation if (!taskRegistered) { - BackgroundTaskBuilder builder; + builder = BackgroundTaskBuilder(); builder.Name(backgroundTaskName); PushNotificationTrigger trigger{}; @@ -215,8 +218,6 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation throw winrt::hresult_not_implemented(); } } - - registeredTask = builder.Register(); } } @@ -238,6 +239,12 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation &cookie)); } } + + if (builder) + { + registeredTask = builder.Register(); + } + return PushNotificationRegistrationToken{ cookie, registeredTask }; } @@ -248,9 +255,9 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { for (auto task : BackgroundTaskRegistration::AllTasks()) { - if (task.Value().Name() == backgroundTaskName) + if (task.Value().Name() == token.TaskRegistration().Name()) { - task.Value().Unregister(false /*cancel task*/); + task.Value().Unregister(true); } } } diff --git a/dev/PushNotifications/PushNotificationManager.h b/dev/PushNotifications/PushNotificationManager.h index 572cdf5dc3..f48373c229 100644 --- a/dev/PushNotifications/PushNotificationManager.h +++ b/dev/PushNotifications/PushNotificationManager.h @@ -13,7 +13,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation static winrt::Windows::Foundation::IAsyncOperationWithProgress CreateChannelAsync(winrt::guid remoteId); private: - static bool isChannelRequestRetryable(const winrt::hresult& hrException); + static bool IsChannelRequestRetryable(const winrt::hresult& hrException); }; } namespace winrt::Microsoft::Windows::PushNotifications::factory_implementation diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp index 657511b635..29beb4aab1 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp @@ -7,11 +7,14 @@ #include "PushNotificationReceivedEventArgs.h" #include "Microsoft.Windows.PushNotifications.PushNotificationReceivedEventArgs.g.cpp" #include +#include +#include "ValueMarshaling.h" namespace winrt { using namespace Windows::ApplicationModel::Background; using namespace Windows::Storage::Streams; + using namespace Windows::Storage; using namespace Windows::Networking::PushNotifications; } @@ -49,42 +52,37 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation winrt::BackgroundTaskDeferral PushNotificationReceivedEventArgs::GetDeferral() { - if (m_backgroundTaskInstance) - { - return m_backgroundTaskInstance.GetDeferral(); - } - // winrt::throw_hresult(); + THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); + + return m_backgroundTaskInstance.GetDeferral(); } winrt::event_token PushNotificationReceivedEventArgs::Canceled(winrt::BackgroundTaskCanceledEventHandler const& handler) { - if (m_backgroundTaskInstance) - { - return m_backgroundTaskInstance.Canceled(handler); - } - return winrt::event_token{}; + THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); + + return m_backgroundTaskInstance.Canceled(handler); } + void PushNotificationReceivedEventArgs::Canceled(winrt::event_token const& token) noexcept { - if (m_backgroundTaskInstance) - { - m_backgroundTaskInstance.Canceled(token); - } + THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_backgroundTaskInstance, "Foreground activation cannot call this."); + + m_backgroundTaskInstance.Canceled(token); } + bool PushNotificationReceivedEventArgs::Handled() { - if (m_args) - { - return m_args.Cancel(); - } - return false; + THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_args, "Background activation cannot call this."); + + return m_args.Cancel(); } + void PushNotificationReceivedEventArgs::Handled(bool value) { - if (m_args) - { - m_args.Cancel(value); - } + THROW_HR_IF_NULL_MSG(E_ILLEGAL_METHOD_CALL, m_args, "Background activation cannot call this."); + + m_args.Cancel(value); } } diff --git a/test/TestApps/PushNotificationsDemoApp/main.cpp b/test/TestApps/PushNotificationsDemoApp/main.cpp index 2c9311b29f..66f82c2460 100644 --- a/test/TestApps/PushNotificationsDemoApp/main.cpp +++ b/test/TestApps/PushNotificationsDemoApp/main.cpp @@ -20,7 +20,7 @@ using namespace winrt::Windows::ApplicationModel::Background; // BackgroundTask time_t ltime; char buf[SIZE]; -void RequestChannel() +winrt::Windows::Foundation::IAsyncOperation RequestChannelAsync() { // Register the AAD RemoteIdentifier for the App to receive Push auto channelOperation = PushNotificationManager::CreateChannelAsync( @@ -28,9 +28,7 @@ void RequestChannel() // Setup the inprogress event handler channelOperation.Progress( - []( - IAsyncOperationWithProgress const& sender, - PushNotificationCreateChannelStatus const& args) + [](auto&& sender, auto&& args) { if (args.status == PushNotificationChannelStatus::InProgress) { @@ -46,43 +44,59 @@ void RequestChannel() } }); - winrt::event_token pushToken; + auto result = co_await channelOperation; - // Setup the completed event handler - channelOperation.Completed( - [&]( - IAsyncOperationWithProgress const& sender, - AsyncStatus const asyncStatus) - { - auto result = sender.GetResults(); - if (result.Status() == PushNotificationChannelStatus::CompletedSuccess) - { - auto channelUri = result.Channel().Uri(); - - std::cout << "channelUri: " << winrt::to_string(channelUri.ToString()) << std::endl << std::endl; + if (result.Status() == PushNotificationChannelStatus::CompletedSuccess) + { + auto channelUri = result.Channel().Uri(); - auto channelExpiry = result.Channel().ExpirationTime(); + std::cout << "channelUri: " << winrt::to_string(channelUri.ToString()) << std::endl << std::endl; - // Register Push Event for Foreground - pushToken = result.Channel().PushReceived([&](const auto&, PushNotificationReceivedEventArgs args) - { - auto payload = args.Payload(); + auto channelExpiry = result.Channel().ExpirationTime(); - // Do stuff to process the raw payload - std::string payloadString(payload.begin(), payload.end()); - std::cout << "Push notification content received from FOREGROUND: " << payloadString << std::endl << std::endl; - args.Handled(true); - }); - } - else if (result.Status() == PushNotificationChannelStatus::CompletedFailure) + // Register Push Event for Foreground + result.Channel().PushReceived([](const auto&, PushNotificationReceivedEventArgs const& args) { - LOG_HR_MSG(result.ExtendedError(), "We hit a critical non-retryable error with channel request!"); - } - }); + auto payload = args.Payload(); + + // Do stuff to process the raw payload + std::string payloadString(payload.begin(), payload.end()); + std::cout << "Push notification content received from FOREGROUND: " << payloadString << std::endl << std::endl; + args.Handled(true); + }); + // Caller's responsibility to keep the channel alive + co_return result.Channel(); + } + else if (result.Status() == PushNotificationChannelStatus::CompletedFailure) + { + LOG_HR_MSG(result.ExtendedError(), "We hit a critical non-retryable error with channel request!"); + co_return nullptr; + } + else + { + LOG_HR_MSG(result.ExtendedError(), "Some other failure occurred."); + co_return nullptr; + } + +}; + +winrt::Microsoft::Windows::PushNotifications::PushNotificationChannel RequestChannel() +{ + auto task = RequestChannelAsync(); + if (task.wait_for(std::chrono::seconds(960)) != AsyncStatus::Completed) + { + task.Cancel(); + return nullptr; + } + + auto result = task.GetResults(); + return result; } int main() { + winrt::init_apartment(); + time(<ime); ctime_s(buf, sizeof buf, <ime); std::cout << "Project Reunion Push Notification Test App: " << buf << std::endl; @@ -114,7 +128,7 @@ int main() } else if (kind == ExtendedActivationKind::Launch) { - RequestChannel(); + PushNotificationChannel channel = RequestChannel(); std::cout << "Press 'Enter' at any time to exit App." << std::endl << std::endl; std::cin.ignore(); } From bb5cee73d8392d93a134931b3abcfe96aa55740c Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Tue, 18 May 2021 19:10:15 -0700 Subject: [PATCH 14/53] Fixed some more nits --- dev/PushNotifications/PushNotificationChannel.h | 2 -- test/TestApps/PushNotificationsDemoApp/main.cpp | 2 -- .../PushNotificationsDemoPackage/Package.appxmanifest | 4 ++-- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/dev/PushNotifications/PushNotificationChannel.h b/dev/PushNotifications/PushNotificationChannel.h index 062ab52ea8..aa223c0d5f 100644 --- a/dev/PushNotifications/PushNotificationChannel.h +++ b/dev/PushNotifications/PushNotificationChannel.h @@ -5,8 +5,6 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { struct PushNotificationChannel : PushNotificationChannelT { - PushNotificationChannel() = default; - PushNotificationChannel(winrt::Windows::Networking::PushNotifications::PushNotificationChannel const& channel); winrt::Windows::Foundation::Uri Uri(); winrt::Windows::Foundation::DateTime ExpirationTime(); diff --git a/test/TestApps/PushNotificationsDemoApp/main.cpp b/test/TestApps/PushNotificationsDemoApp/main.cpp index 66f82c2460..d46ceb91a3 100644 --- a/test/TestApps/PushNotificationsDemoApp/main.cpp +++ b/test/TestApps/PushNotificationsDemoApp/main.cpp @@ -95,8 +95,6 @@ winrt::Microsoft::Windows::PushNotifications::PushNotificationChannel RequestCha int main() { - winrt::init_apartment(); - time(<ime); ctime_s(buf, sizeof buf, <ime); std::cout << "Project Reunion Push Notification Test App: " << buf << std::endl; diff --git a/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest b/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest index e91ef0d8a2..67f9bf3087 100644 --- a/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest +++ b/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest @@ -59,7 +59,7 @@ - - + + \ No newline at end of file From 0de79cf1126cd9d087159c401144081ae5aa92e1 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Thu, 20 May 2021 15:46:50 -0700 Subject: [PATCH 15/53] Added some nit fixes --- .../PushNotificationManager.cpp | 73 +++++++++++-------- .../PushNotificationReceivedEventArgs.cpp | 17 +---- .../PushNotificationReceivedEventArgs.h | 2 +- test/PushNotificationTests/Shared.cpp | 6 +- 4 files changed, 50 insertions(+), 48 deletions(-) diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp index a59aad6538..fe469a9b4d 100644 --- a/dev/PushNotifications/PushNotificationManager.cpp +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -181,8 +181,8 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation PushNotificationRegistrationToken PushNotificationManager::RegisterActivator(PushNotificationActivationInfo const& details) { - winrt::guid taskClsid = details.TaskClsid(); - THROW_HR_IF(E_INVALIDARG, taskClsid == winrt::guid(GUID_NULL)); + GUID taskClsid = details.TaskClsid(); + THROW_HR_IF(E_INVALIDARG, taskClsid == GUID_NULL); DWORD cookie = 0; BackgroundTaskRegistration registeredTask = nullptr; @@ -190,54 +190,67 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation if (WI_IsFlagSet(details.Kind(), PushNotificationRegistrationKind::PushTrigger)) { + winrt::hstring taskClsidStr = winrt::to_hstring(taskClsid); auto tasks = BackgroundTaskRegistration::AllTasks(); - bool taskRegistered = std::any_of(begin(tasks), end(tasks), [&](auto&& task) { return task.Value().Name() == backgroundTaskName; }); + bool taskRegistered = std::any_of(begin(tasks), end(tasks), + [&](auto&& task) + { + std::wstring backgroundTaskNameStr = task.Value().Name().c_str(); + if (backgroundTaskNameStr.find(backgroundTaskName) != std::wstring::npos) + { + if (backgroundTaskNameStr.find(taskClsidStr) != std::wstring::npos) + { + return true; + } + else + { + // Unregister background task here + throw winrt::hresult_invalid_argument(L"RegisterActivator has different clsid registered."); + } + }; + return false; + }); if (!taskRegistered) { builder = BackgroundTaskBuilder(); - builder.Name(backgroundTaskName); + builder.Name(backgroundTaskName + taskClsidStr.c_str()); PushNotificationTrigger trigger{}; builder.SetTrigger(trigger); - if (taskClsid != winrt::guid()) + auto builder5 = builder.try_as(); + if (IsPackagedProcess() && builder5) { - auto builder5 = builder.try_as(); - if (IsPackagedProcess() && builder5) - { - builder5.SetTaskEntryPointClsid(taskClsid); - winrt::com_array conditions = details.GetConditions(); - for (auto condition : conditions) - { - builder.AddCondition(condition); - } - } - else + builder5.SetTaskEntryPointClsid(taskClsid); + winrt::com_array conditions = details.GetConditions(); + for (auto condition : conditions) { - throw winrt::hresult_not_implemented(); + builder.AddCondition(condition); } } + else + { + throw winrt::hresult_not_implemented(); + } } } if (WI_IsFlagSet(details.Kind(), PushNotificationRegistrationKind::ComActivator)) { - if (taskClsid != winrt::guid()) { - { - auto lock = g_lock.lock(); - // Define handle that will be set during background task execution - g_waitHandleForArgs = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); - } - - THROW_IF_FAILED(::CoRegisterClassObject( - taskClsid, - winrt::make().get(), - CLSCTX_LOCAL_SERVER, - REGCLS_MULTIPLEUSE, - &cookie)); + auto lock = g_lock.lock(); + // Define handle that will be set during background task execution + g_waitHandleForArgs = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); + THROW_HR_IF_NULL(E_UNEXPECTED, g_waitHandleForArgs); } + + THROW_IF_FAILED(::CoRegisterClassObject( + taskClsid, + winrt::make().get(), + CLSCTX_LOCAL_SERVER, + REGCLS_MULTIPLEUSE, + &cookie)); } if (builder) diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp index 29beb4aab1..717c08aa42 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp @@ -20,20 +20,9 @@ namespace winrt namespace winrt::Microsoft::Windows::PushNotifications::implementation { - winrt::com_array GetRawPayload(RawNotification const& rawNotification) - { - IBuffer rawContentAsBuffer = rawNotification.ContentBytes(); - DataReader dataReader = DataReader::FromBuffer(rawContentAsBuffer); - - winrt::com_array rawPayload = winrt::com_array(rawContentAsBuffer.Length()); - dataReader.ReadBytes(rawPayload); - - return rawPayload; - } - - PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::IBackgroundTaskInstance const& backgroundTask): m_backgroundTaskInstance(backgroundTask), m_rawNotification(GetRawPayload(backgroundTask.TriggerDetails().as())) {} + PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::IBackgroundTaskInstance const& backgroundTask): m_backgroundTaskInstance(backgroundTask), m_rawNotification(backgroundTask.TriggerDetails().as().ContentBytes()) {} - PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::PushNotificationReceivedEventArgs const& args): m_args(args), m_rawNotification(GetRawPayload(args.RawNotification())) {} + PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::PushNotificationReceivedEventArgs const& args): m_args(args), m_rawNotification(args.RawNotification().ContentBytes()) {} winrt::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs PushNotificationReceivedEventArgs::CreateFromBackgroundTaskInstance(winrt::IBackgroundTaskInstance const& backgroundTask) { @@ -47,7 +36,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation winrt::com_array PushNotificationReceivedEventArgs::Payload() { - return { m_rawNotification.begin(), m_rawNotification.end() }; + return { m_rawNotification.data(), m_rawNotification.data() + (m_rawNotification.Length() * sizeof(uint8_t)) }; } winrt::BackgroundTaskDeferral PushNotificationReceivedEventArgs::GetDeferral() diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.h b/dev/PushNotifications/PushNotificationReceivedEventArgs.h index 1f97c44101..d55b632537 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.h +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.h @@ -19,7 +19,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation void Handled(bool value); private: - const winrt::com_array m_rawNotification{}; + const winrt::Windows::Storage::Streams::IBuffer m_rawNotification{}; const winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance m_backgroundTaskInstance = nullptr; const winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs m_args = nullptr; }; diff --git a/test/PushNotificationTests/Shared.cpp b/test/PushNotificationTests/Shared.cpp index 28e2ae08cb..059d69489f 100644 --- a/test/PushNotificationTests/Shared.cpp +++ b/test/PushNotificationTests/Shared.cpp @@ -56,14 +56,14 @@ namespace Test::PushNotifications std::wstring args{ action + L" TrustedPeople " + path }; // VERIFY_ARE_NOT_EQUAL(args, args); auto process = Execute(L"%SystemRoot%\\system32\\certutil.exe", - args.c_str(), g_deploymentDir); + args, g_deploymentDir); // Wait for the cer to be installed. auto waitResult = WaitForSingleObject(process.get(), c_phaseTimeout); if (waitResult != WAIT_OBJECT_0) { - auto lastError = GetLastError(); - VERIFY_WIN32_FAILED(lastError); + if (waitResult == WAIT_FAILED) VERIFY_WIN32_SUCCEEDED(GetLastError()); + VERIFY_ARE_EQUAL(waitResult, WAIT_OBJECT_0); } // Make sure the exitcode for the tool is success. From 0fef22d57ba013652c51d7a84adf8de40f17e8b5 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Thu, 20 May 2021 18:04:35 -0700 Subject: [PATCH 16/53] Replace Kind -> Option --- .../GetRawNotificationEventArgs.h | 13 +++++++----- .../PushNotificationActivationInfo.cpp | 6 +++--- .../PushNotificationActivationInfo.h | 6 +++--- .../PushNotificationBackgroundTask.h | 3 ++- .../PushNotificationManager.cpp | 11 +++++----- .../PushNotificationManager.h | 2 +- dev/PushNotifications/PushNotifications.idl | 21 +++++++++---------- .../PushNotificationsDemoApp/main.cpp | 4 ++-- .../PushNotificationsTestApp/main.cpp | 10 ++++----- 9 files changed, 40 insertions(+), 36 deletions(-) diff --git a/dev/PushNotifications/GetRawNotificationEventArgs.h b/dev/PushNotifications/GetRawNotificationEventArgs.h index b655da3315..81cfd44d48 100644 --- a/dev/PushNotifications/GetRawNotificationEventArgs.h +++ b/dev/PushNotifications/GetRawNotificationEventArgs.h @@ -10,18 +10,21 @@ namespace winrt::Microsoft::Windows::PushNotifications { static winrt::Windows::Foundation::IInspectable Deserialize(winrt::Windows::Foundation::Uri const&) { - winrt::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs args = nullptr; - { auto lock = g_lock.lock(); - THROW_HR_IF_NULL_MSG(E_UNEXPECTED, g_waitHandleForArgs, "PushNotificationManager::RegisterActivator has not been called."); + if (g_activatedEventArgs) + { + return g_activatedEventArgs; + } + + THROW_HR_IF_NULL_MSG(E_UNEXPECTED, g_waitHandleForArgs, "PushNotificationManager::RegisterActivator has not been called."); } if (WaitForSingleObject(g_waitHandleForArgs.get(), 1000) == WAIT_OBJECT_0) { auto lock = g_lock.lock(); - std::swap(args, g_activatedEventArgs); + return g_activatedEventArgs; } - return args; + winrt::throw_hresult(HRESULT_FROM_WIN32(ERROR_TIMEOUT)); } } diff --git a/dev/PushNotifications/PushNotificationActivationInfo.cpp b/dev/PushNotifications/PushNotificationActivationInfo.cpp index 45d00050c1..358993eb8b 100644 --- a/dev/PushNotifications/PushNotificationActivationInfo.cpp +++ b/dev/PushNotifications/PushNotificationActivationInfo.cpp @@ -12,16 +12,16 @@ namespace winrt namespace winrt::Microsoft::Windows::PushNotifications::implementation { - PushNotificationActivationInfo::PushNotificationActivationInfo(winrt::PushNotificationRegistrationKind const& kind, winrt::guid const& taskClsid) : m_kind(kind), m_taskClsid(taskClsid) {} + PushNotificationActivationInfo::PushNotificationActivationInfo(winrt::PushNotificationRegistrationOption const& option, winrt::guid const& taskClsid) : m_option(option), m_taskClsid(taskClsid) {} winrt::guid PushNotificationActivationInfo::TaskClsid() { return m_taskClsid; } - winrt::PushNotificationRegistrationKind PushNotificationActivationInfo::Kind() + winrt::PushNotificationRegistrationOption PushNotificationActivationInfo::Option() { - return m_kind; + return m_option; } winrt::com_array PushNotificationActivationInfo::GetConditions() diff --git a/dev/PushNotifications/PushNotificationActivationInfo.h b/dev/PushNotifications/PushNotificationActivationInfo.h index 9ce88c6453..01d377bb42 100644 --- a/dev/PushNotifications/PushNotificationActivationInfo.h +++ b/dev/PushNotifications/PushNotificationActivationInfo.h @@ -5,14 +5,14 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { struct PushNotificationActivationInfo : PushNotificationActivationInfoT { - PushNotificationActivationInfo(Microsoft::Windows::PushNotifications::PushNotificationRegistrationKind const& kind, winrt::guid const& taskClsid); + PushNotificationActivationInfo(Microsoft::Windows::PushNotifications::PushNotificationRegistrationOption const& option, winrt::guid const& taskClsid); winrt::guid TaskClsid(); - Microsoft::Windows::PushNotifications::PushNotificationRegistrationKind Kind(); + Microsoft::Windows::PushNotifications::PushNotificationRegistrationOption Option(); winrt::com_array GetConditions(); void SetConditions(array_view conditions); private: - const Microsoft::Windows::PushNotifications::PushNotificationRegistrationKind m_kind; + const Microsoft::Windows::PushNotifications::PushNotificationRegistrationOption m_option; const winrt::guid m_taskClsid; winrt::com_array m_backgroundConditions{}; wil::srwlock m_lock; diff --git a/dev/PushNotifications/PushNotificationBackgroundTask.h b/dev/PushNotifications/PushNotificationBackgroundTask.h index 331fb7f3af..e065395cc5 100644 --- a/dev/PushNotifications/PushNotificationBackgroundTask.h +++ b/dev/PushNotifications/PushNotificationBackgroundTask.h @@ -21,8 +21,9 @@ struct PushNotificationBackgroundTaskFactory : winrt::implements().as(interfaceId, object); } - HRESULT __stdcall LockServer(BOOL) noexcept final + HRESULT __stdcall LockServer(BOOL lock) noexcept final { + // return CoLockObjectExternal(); return S_OK; } }; diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp index fe469a9b4d..78bfe7c326 100644 --- a/dev/PushNotifications/PushNotificationManager.cpp +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -183,12 +183,13 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { GUID taskClsid = details.TaskClsid(); THROW_HR_IF(E_INVALIDARG, taskClsid == GUID_NULL); + THROW_HR_IF(E_INVALIDARG, !(WI_IsFlagSet(details.Option(), PushNotificationRegistrationOption::PushTrigger) || WI_IsFlagSet(details.Option(), PushNotificationRegistrationOption::ComActivator))); DWORD cookie = 0; BackgroundTaskRegistration registeredTask = nullptr; BackgroundTaskBuilder builder = nullptr; - if (WI_IsFlagSet(details.Kind(), PushNotificationRegistrationKind::PushTrigger)) + if (WI_IsFlagSet(details.Option(), PushNotificationRegistrationOption::PushTrigger)) { winrt::hstring taskClsidStr = winrt::to_hstring(taskClsid); auto tasks = BackgroundTaskRegistration::AllTasks(); @@ -236,7 +237,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } } - if (WI_IsFlagSet(details.Kind(), PushNotificationRegistrationKind::ComActivator)) + if (WI_IsFlagSet(details.Option(), PushNotificationRegistrationOption::ComActivator)) { { auto lock = g_lock.lock(); @@ -261,10 +262,10 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation return PushNotificationRegistrationToken{ cookie, registeredTask }; } - void PushNotificationManager::UnregisterActivator(PushNotificationRegistrationToken const& token, PushNotificationRegistrationKind const& kind) + void PushNotificationManager::UnregisterActivator(PushNotificationRegistrationToken const& token, PushNotificationRegistrationOption const& option) { - if (WI_IsFlagSet(kind, PushNotificationRegistrationKind::PushTrigger)) + if (WI_IsFlagSet(option, PushNotificationRegistrationOption::PushTrigger)) { for (auto task : BackgroundTaskRegistration::AllTasks()) { @@ -275,7 +276,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } } - if (WI_IsFlagSet(kind, PushNotificationRegistrationKind::ComActivator) && token.Cookie()) + if (WI_IsFlagSet(option, PushNotificationRegistrationOption::ComActivator) && token.Cookie()) { LOG_IF_FAILED(::CoRevokeClassObject(static_cast(token.Cookie()))); } diff --git a/dev/PushNotifications/PushNotificationManager.h b/dev/PushNotifications/PushNotificationManager.h index f48373c229..172c6edbcc 100644 --- a/dev/PushNotifications/PushNotificationManager.h +++ b/dev/PushNotifications/PushNotificationManager.h @@ -8,7 +8,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation PushNotificationManager() = delete; static Microsoft::Windows::PushNotifications::PushNotificationRegistrationToken RegisterActivator(Microsoft::Windows::PushNotifications::PushNotificationActivationInfo const& details); - static void UnregisterActivator(Microsoft::Windows::PushNotifications::PushNotificationRegistrationToken const& token, Microsoft::Windows::PushNotifications::PushNotificationRegistrationKind const& kind); + static void UnregisterActivator(Microsoft::Windows::PushNotifications::PushNotificationRegistrationToken const& token, Microsoft::Windows::PushNotifications::PushNotificationRegistrationOption const& option); static winrt::Windows::Foundation::IAsyncOperationWithProgress CreateChannelAsync(winrt::guid remoteId); diff --git a/dev/PushNotifications/PushNotifications.idl b/dev/PushNotifications/PushNotifications.idl index 81b264bc4c..517a9dea29 100644 --- a/dev/PushNotifications/PushNotifications.idl +++ b/dev/PushNotifications/PushNotifications.idl @@ -27,25 +27,24 @@ namespace Microsoft.Windows.PushNotifications }; [flags] - enum PushNotificationRegistrationKind + enum PushNotificationRegistrationOption { PushTrigger = 0x1, // Registers a Push Trigger with Background Infrastructure ComActivator = 0x2, // Registers the Project Reunion Background Task component as an InProc COM server }; [experimental] - // An abstraction over the activation Registration flow runtimeclass PushNotificationActivationInfo { - // Initialize using a RegistrationKind 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 Project Reunion Background Task component will be Registered as an InProc COM server - PushNotificationActivationInfo(PushNotificationRegistrationKind kind, Guid taskClsid); + // Initialize using a RegistrationOption and optionally defined parameters like manifest defined activatorId + // 1) If option = PushTrigger is specified, only the Push Trigger will be Registered with Background Infra + // 2) If option = ComActivator is specified, the Project Reunion Background Task component will be Registered as an InProc COM server + PushNotificationActivationInfo(PushNotificationRegistrationOption option, Guid taskClsid); // The CLSID associated with the Client COM server that Project Reunion will activate Guid TaskClsid{ get; }; - PushNotificationRegistrationKind Kind{ get; }; + PushNotificationRegistrationOption Option{ get; }; // The conditions under which Push Triggers would execute Windows.ApplicationModel.Background.IBackgroundCondition[] GetConditions(); @@ -129,10 +128,10 @@ namespace Microsoft.Windows.PushNotifications // Register an activator using an ActivationInfo context and return a RegistrationToken static PushNotificationRegistrationToken RegisterActivator(PushNotificationActivationInfo details); - // Unregister any activator if present using a token and registrationKind - // 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 - static void UnregisterActivator(PushNotificationRegistrationToken token, PushNotificationRegistrationKind kind); + // Unregister any activator if present using a token and registrationOption + // 1) If option = PushTrigger is specified, the trigger itself will be removed + // 2) If option = ComActivator is specified, the Project Reunion Background Task component will no longer act as an InProc COM Server + static void UnregisterActivator(PushNotificationRegistrationToken token, PushNotificationRegistrationOption option); // Request a Push Channel using an encoded AAD GUID identifier from WNS. static Windows.Foundation.IAsyncOperationWithProgress CreateChannelAsync(Guid remoteId); diff --git a/test/TestApps/PushNotificationsDemoApp/main.cpp b/test/TestApps/PushNotificationsDemoApp/main.cpp index d46ceb91a3..d0e50cf920 100644 --- a/test/TestApps/PushNotificationsDemoApp/main.cpp +++ b/test/TestApps/PushNotificationsDemoApp/main.cpp @@ -100,7 +100,7 @@ int main() std::cout << "Project Reunion Push Notification Test App: " << buf << std::endl; PushNotificationActivationInfo info( - PushNotificationRegistrationKind::PushTrigger | PushNotificationRegistrationKind::ComActivator, + PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator, winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2")); // same clsid as app manifest auto token = PushNotificationManager::RegisterActivator(info); @@ -137,6 +137,6 @@ int main() std::cin.ignore(); } - PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationKind::ComActivator); + PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationOption::ComActivator); return 0; } diff --git a/test/TestApps/PushNotificationsTestApp/main.cpp b/test/TestApps/PushNotificationsTestApp/main.cpp index 27f016eae0..b3d70eb417 100644 --- a/test/TestApps/PushNotificationsTestApp/main.cpp +++ b/test/TestApps/PushNotificationsTestApp/main.cpp @@ -275,7 +275,7 @@ bool ActivatorTest() try { PushNotificationActivationInfo info( - PushNotificationRegistrationKind::PushTrigger | PushNotificationRegistrationKind::ComActivator, + PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator, c_fakeComServerId); auto token = PushNotificationManager::RegisterActivator(info); @@ -284,7 +284,7 @@ bool ActivatorTest() return false; } - PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationKind::PushTrigger | PushNotificationRegistrationKind::ComActivator); + PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); } catch (...) { @@ -325,7 +325,7 @@ int main() initUnitTestMapping(); PushNotificationActivationInfo info( - PushNotificationRegistrationKind::PushTrigger | PushNotificationRegistrationKind::ComActivator, + PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator, winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2")); // same clsid as app manifest auto token = PushNotificationManager::RegisterActivator(info); @@ -341,7 +341,7 @@ int main() std::cout << unitTest << std::endl; - PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationKind::PushTrigger | PushNotificationRegistrationKind::ComActivator); + PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); // Switch on this variable to run specific components (uri://ComponentToTest) auto output = runUnitTest(unitTest); @@ -362,7 +362,7 @@ int main() PushNotificationReceivedEventArgs pushArgs = args.Data().as(); auto payload = pushArgs.Payload(); std::wstring payloadString(payload.begin(), payload.end()); - PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationKind::PushTrigger | PushNotificationRegistrationKind::ComActivator); + PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); if (!payloadString.compare(c_rawNotificationPayload)) { signalPhase(c_testProtocolScheme_Packaged); From 7dc5a87bfb24cbf30fd0adf6ac7da208c9eca52e Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Sun, 23 May 2021 19:14:39 -0700 Subject: [PATCH 17/53] Added cleanup to TAEF test --- .../PushNotificationBackgroundTask.h | 3 +- .../PushNotificationManager.cpp | 4 +- .../PushNotificationsTestApp/main.cpp | 285 +++++------------- 3 files changed, 76 insertions(+), 216 deletions(-) diff --git a/dev/PushNotifications/PushNotificationBackgroundTask.h b/dev/PushNotifications/PushNotificationBackgroundTask.h index e065395cc5..331fb7f3af 100644 --- a/dev/PushNotifications/PushNotificationBackgroundTask.h +++ b/dev/PushNotifications/PushNotificationBackgroundTask.h @@ -21,9 +21,8 @@ struct PushNotificationBackgroundTaskFactory : winrt::implements().as(interfaceId, object); } - HRESULT __stdcall LockServer(BOOL lock) noexcept final + HRESULT __stdcall LockServer(BOOL) noexcept final { - // return CoLockObjectExternal(); return S_OK; } }; diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp index 78bfe7c326..eaa7364474 100644 --- a/dev/PushNotifications/PushNotificationManager.cpp +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -181,10 +181,10 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation PushNotificationRegistrationToken PushNotificationManager::RegisterActivator(PushNotificationActivationInfo const& details) { - GUID taskClsid = details.TaskClsid(); - THROW_HR_IF(E_INVALIDARG, taskClsid == GUID_NULL); + THROW_HR_IF(E_INVALIDARG, details.TaskClsid() == winrt::guid()); THROW_HR_IF(E_INVALIDARG, !(WI_IsFlagSet(details.Option(), PushNotificationRegistrationOption::PushTrigger) || WI_IsFlagSet(details.Option(), PushNotificationRegistrationOption::ComActivator))); + GUID taskClsid = details.TaskClsid(); DWORD cookie = 0; BackgroundTaskRegistration registeredTask = nullptr; BackgroundTaskBuilder builder = nullptr; diff --git a/test/TestApps/PushNotificationsTestApp/main.cpp b/test/TestApps/PushNotificationsTestApp/main.cpp index b3d70eb417..816f5aab50 100644 --- a/test/TestApps/PushNotificationsTestApp/main.cpp +++ b/test/TestApps/PushNotificationsTestApp/main.cpp @@ -22,6 +22,8 @@ static std::map switchMapping; winrt::guid remoteId1(L"a2e4a323-b518-4799-9e80-0b37aeb0d225"); winrt::guid remoteId2(L"CA1A4AB2-AC1D-4EFC-A132-E5A191CA285A"); winrt::guid remoteId3(L"40FCE789-C6BF-4F47-A6CF-6B9C1DCE31BA"); +PushNotificationRegistrationToken appToken = nullptr; +PushNotificationRegistrationToken fakeToken = nullptr; void signalPhase(const std::wstring& phaseEventName) { @@ -59,232 +61,82 @@ bool ChannelRequestUsingNullRemoteId() return (hr == E_INVALIDARG); } -bool ChannelRequestUsingRemoteId() +HRESULT ChannelRequestHelper(IAsyncOperationWithProgress const& channelOperation) { - auto channelOperationResult = S_OK; - auto channelOperation = PushNotificationManager::CreateChannelAsync(remoteId1); - - switch (channelOperation.wait_for(std::chrono::seconds(960))) + if (channelOperation.wait_for(std::chrono::seconds(960)) != AsyncStatus::Completed) { - case AsyncStatus::Completed: - { - auto channelResult = channelOperation.GetResults(); - if (channelResult.Status() == PushNotificationChannelStatus::CompletedSuccess) - { - channelResult.Channel().Close(); // Avoids using cached channel everytime the test runs - } - else if (channelResult.Status() == PushNotificationChannelStatus::CompletedFailure) - { - channelOperationResult = channelResult.ExtendedError(); - } - break; + channelOperation.Cancel(); + return ERROR_TIMEOUT; // timed out or failed } - default: - channelOperationResult = ERROR_TIMEOUT; - break; + + auto result = channelOperation.GetResults(); + auto status = result.Status(); + if (status != PushNotificationChannelStatus::CompletedSuccess) + { + return result.ExtendedError(); // did not produce a channel } - return (channelOperationResult == S_OK); + result.Channel().Close(); + return S_OK; } -bool MultipleChannelRequestUsingSameRemoteId() +bool ChannelRequestUsingRemoteId() { - auto channelOperationResult1 = S_OK; - auto channelOperation1 = PushNotificationManager::CreateChannelAsync(remoteId1); - - auto channelOperationResult2 = S_OK; - - auto channelOperation2 = PushNotificationManager::CreateChannelAsync(remoteId1); - - switch (channelOperation2.wait_for(std::chrono::seconds(960))) - { - case AsyncStatus::Completed: - { - auto channelResult2 = channelOperation2.GetResults(); - if (channelResult2.Status() == PushNotificationChannelStatus::CompletedSuccess) - { - channelResult2.Channel().Close(); // Avoids using cached channel everytime the test runs - } - else if (channelResult2.Status() == PushNotificationChannelStatus::CompletedFailure) - { - channelOperationResult2 = channelResult2.ExtendedError(); - } - break; - } + auto channelOperation = PushNotificationManager::CreateChannelAsync(remoteId1); + auto channelOperationResult = ChannelRequestHelper(channelOperation); - default: - channelOperationResult2 = ERROR_TIMEOUT; - break; - } + return channelOperationResult == S_OK; +} - switch (channelOperation1.wait_for(std::chrono::seconds(960))) - { - case AsyncStatus::Completed: - { - auto channelResult1 = channelOperation1.GetResults(); - if (channelResult1.Status() == PushNotificationChannelStatus::CompletedSuccess) - { - channelResult1.Channel().Close(); // Avoids using cached channel everytime the test runs - } - else if (channelResult1.Status() == PushNotificationChannelStatus::CompletedFailure) - { - channelOperationResult1 = channelResult1.ExtendedError(); - } - break; - } +bool MultipleChannelRequestUsingSameRemoteId() +{ - default: - channelOperationResult1 = ERROR_TIMEOUT; - break; - } + auto channelOperation1 = PushNotificationManager::CreateChannelAsync(remoteId1); + auto channelOperation2 = PushNotificationManager::CreateChannelAsync(remoteId1); + auto channelOperationResult2 = ChannelRequestHelper(channelOperation2); + auto channelOperationResult1 = ChannelRequestHelper(channelOperation1); - return (channelOperationResult2 == WPN_E_OUTSTANDING_CHANNEL_REQUEST); + return channelOperationResult2 == WPN_E_OUTSTANDING_CHANNEL_REQUEST; } bool MultipleChannelRequestUsingMultipleRemoteId() { - auto channelOperationResult1 = S_OK; auto channelOperation1 = PushNotificationManager::CreateChannelAsync(remoteId1); - - auto channelOperationResult2 = S_OK; - auto channelOperation2 = PushNotificationManager::CreateChannelAsync(remoteId2); + auto channelOperationResult2 = ChannelRequestHelper(channelOperation2); + auto channelOperationResult1 = ChannelRequestHelper(channelOperation1); - switch (channelOperation2.wait_for(std::chrono::seconds(960))) - { - case AsyncStatus::Completed: - { - auto channelResult2 = channelOperation2.GetResults(); - if (channelResult2.Status() == PushNotificationChannelStatus::CompletedSuccess) - { - channelResult2.Channel().Close(); // Avoids using cached channel everytime the test runs - } - else if (channelResult2.Status() == PushNotificationChannelStatus::CompletedFailure) - { - channelOperationResult2 = channelResult2.ExtendedError(); - } - break; - } - - default: - channelOperationResult2 = ERROR_TIMEOUT; - break; - } - - switch (channelOperation1.wait_for(std::chrono::seconds(960))) - { - case AsyncStatus::Completed: - { - auto channelResult1 = channelOperation1.GetResults(); - if (channelResult1.Status() == PushNotificationChannelStatus::CompletedSuccess) - { - channelResult1.Channel().Close(); // Avoids using cached channel everytime the test runs - } - else if (channelResult1.Status() == PushNotificationChannelStatus::CompletedFailure) - { - channelOperationResult1 = channelResult1.ExtendedError(); - } - break; - } - default: - channelOperationResult1 = ERROR_TIMEOUT; - break; - } - - return (channelOperationResult2 == WPN_E_OUTSTANDING_CHANNEL_REQUEST); + return channelOperationResult2 == WPN_E_OUTSTANDING_CHANNEL_REQUEST; } bool ThreeChannelRequestUsingSameRemoteId() { - auto channelOperationResult1 = S_OK; auto channelOperation1 = PushNotificationManager::CreateChannelAsync(remoteId1); + auto channelOperation2 = PushNotificationManager::CreateChannelAsync(remoteId2); + auto channelOperation3 = PushNotificationManager::CreateChannelAsync(remoteId3); + auto channelOperationResult2 = ChannelRequestHelper(channelOperation2); + auto channelOperationResult3 = ChannelRequestHelper(channelOperation3); + auto channelOperationResult1 = ChannelRequestHelper(channelOperation1); - auto channelOperationResult2 = S_OK; - - auto channelOperation2 = PushNotificationManager::CreateChannelAsync(remoteId1); - - auto channelOperationResult3 = S_OK; - - auto channelOperation3 = PushNotificationManager::CreateChannelAsync(remoteId1); - - switch (channelOperation2.wait_for(std::chrono::seconds(960))) - { - case AsyncStatus::Completed: - { - auto channelResult2 = channelOperation2.GetResults(); - if (channelResult2.Status() == PushNotificationChannelStatus::CompletedSuccess) - { - channelResult2.Channel().Close(); // Avoids using cached channel everytime the test runs - } - else if (channelResult2.Status() == PushNotificationChannelStatus::CompletedFailure) - { - channelOperationResult2 = channelResult2.ExtendedError(); - } - break; - } - default: - channelOperationResult2 = ERROR_TIMEOUT; - break; - } - - switch (channelOperation3.wait_for(std::chrono::seconds(960))) - { - case AsyncStatus::Completed: - { - auto channelResult3 = channelOperation3.GetResults(); - if (channelResult3.Status() == PushNotificationChannelStatus::CompletedSuccess) - { - channelResult3.Channel().Close(); // Avoids using cached channel everytime the test runs - } - else if (channelResult3.Status() == PushNotificationChannelStatus::CompletedFailure) - { - channelOperationResult3 = channelResult3.ExtendedError(); - } - break; - } - default: - channelOperationResult3 = ERROR_TIMEOUT; - break; - } - - switch (channelOperation1.wait_for(std::chrono::seconds(960))) - { - case AsyncStatus::Completed: - { - auto channelResult1 = channelOperation1.GetResults(); - if (channelResult1.Status() == PushNotificationChannelStatus::CompletedSuccess) - { - channelResult1.Channel().Close(); // Avoids using cached channel everytime the test runs - } - else if (channelResult1.Status() == PushNotificationChannelStatus::CompletedFailure) - { - channelOperationResult1 = channelResult1.ExtendedError(); - } - break; - } - default: - channelOperationResult1 = ERROR_TIMEOUT; - break; - } - - return ((channelOperationResult2 == WPN_E_OUTSTANDING_CHANNEL_REQUEST) && (channelOperationResult3 == WPN_E_OUTSTANDING_CHANNEL_REQUEST)); + return channelOperationResult2 == WPN_E_OUTSTANDING_CHANNEL_REQUEST && channelOperationResult3 == WPN_E_OUTSTANDING_CHANNEL_REQUEST; } bool ActivatorTest() { + PushNotificationManager::UnregisterActivator(appToken, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); try { PushNotificationActivationInfo info( PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator, c_fakeComServerId); - auto token = PushNotificationManager::RegisterActivator(info); - if (!token.TaskRegistration()) + fakeToken = PushNotificationManager::RegisterActivator(info); + if (!fakeToken.TaskRegistration()) { return false; } - PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); + PushNotificationManager::UnregisterActivator(fakeToken, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); } catch (...) { @@ -320,15 +172,45 @@ bool runUnitTest(std::string unitTest) } } +// Cleanup function for exiting test app. +void UnregisterClsid() +{ + if (appToken) + { + ::CoRevokeClassObject(static_cast(appToken.Cookie())); + PushNotificationManager::UnregisterActivator(appToken, PushNotificationRegistrationOption::PushTrigger); + } + + if (fakeToken) + { + ::CoRevokeClassObject(static_cast(fakeToken.Cookie())); + PushNotificationManager::UnregisterActivator(fakeToken, PushNotificationRegistrationOption::PushTrigger); + } +} + int main() { initUnitTestMapping(); + bool output = false; + auto scope_exit = wil::scope_exit([&] { + UnregisterClsid(); + if (output) + { + // Signal TAEF that protocol was activated and valid. + signalPhase(c_testProtocolScheme_Packaged); + } + else + { + // Signal TAEF that the test failed + signalPhase(c_testFailureEventName); + } + }); PushNotificationActivationInfo info( PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator, winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2")); // same clsid as app manifest - auto token = PushNotificationManager::RegisterActivator(info); + appToken = PushNotificationManager::RegisterActivator(info); auto args = AppInstance::GetCurrent().GetActivatedEventArgs(); auto kind = args.Kind(); @@ -341,37 +223,16 @@ int main() std::cout << unitTest << std::endl; - PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); - // Switch on this variable to run specific components (uri://ComponentToTest) - auto output = runUnitTest(unitTest); - - if (output) - { - // Signal TAEF that protocol was activated and valid. - signalPhase(c_testProtocolScheme_Packaged); - } - else - { - // Signal TAEF that the test failed - signalPhase(c_testFailureEventName); - } + output = runUnitTest(unitTest); } else if (kind == ExtendedActivationKind::Push) { PushNotificationReceivedEventArgs pushArgs = args.Data().as(); auto payload = pushArgs.Payload(); std::wstring payloadString(payload.begin(), payload.end()); - PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); - if (!payloadString.compare(c_rawNotificationPayload)) - { - signalPhase(c_testProtocolScheme_Packaged); - } - else - { - // Signal TAEF that the test failed - signalPhase(c_testFailureEventName); - } + + output = !payloadString.compare(c_rawNotificationPayload); } return 0; From ddac203369e13edd7d7073b043dfbcf6598fcee5 Mon Sep 17 00:00:00 2001 From: Sharath Manchala <10109130+sharath2727@users.noreply.github.com> Date: Mon, 24 May 2021 10:19:55 -0700 Subject: [PATCH 18/53] Address comments for createchannelasync --- .../PushNotificationManager.cpp | 63 ++++++++----------- .../PushNotificationManager.h | 2 +- 2 files changed, 26 insertions(+), 39 deletions(-) diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp index eaa7364474..42c2d88ad8 100644 --- a/dev/PushNotifications/PushNotificationManager.cpp +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -33,9 +33,9 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation inline constexpr std::uint32_t c_maxBackoffSeconds{ 960 }; inline constexpr std::uint32_t c_minBackoffSeconds{ 30 }; - const HRESULT WNP_E_NOT_CONNECTED = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x880403E8L); - const HRESULT WNP_E_RECONNECTING = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x880403E9L); - const HRESULT WNP_E_BIND_USER_BUSY = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x880403FEL); + const HRESULT WNP_E_NOT_CONNECTED = (HRESULT)0x880403E8L; + const HRESULT WNP_E_RECONNECTING = (HRESULT)0x880403E9L; + const HRESULT WNP_E_BIND_USER_BUSY = (HRESULT)0x880403FEL; bool PushNotificationManager::IsChannelRequestRetryable(const hresult& hr) { @@ -46,7 +46,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation case WPN_E_OUTSTANDING_CHANNEL_REQUEST: case WNP_E_RECONNECTING: case WNP_E_BIND_USER_BUSY: - case RPC_S_SERVER_UNAVAILABLE: + case HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE): return true; default: return false; @@ -71,7 +71,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation return true; } - winrt::IAsyncOperationWithProgress PushNotificationManager::CreateChannelAsync(winrt::guid remoteId) + winrt::IAsyncOperationWithProgress PushNotificationManager::CreateChannelAsync(const winrt::guid &remoteId) { static bool s_remoteIdInProgress; static wil::critical_section s_lock; @@ -79,9 +79,8 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation THROW_HR_IF(E_INVALIDARG, (remoteId == winrt::guid())); // API supports channel requests only for packaged applications for v0.8 version - THROW_HR_IF(E_NOTIMPL, (IsPackagedProcess() == false)); + THROW_HR_IF(E_NOTIMPL, !IsPackagedProcess()); - winrt::Microsoft::Windows::PushNotifications::PushNotificationCreateChannelResult channelResult{ nullptr }; { auto lock = s_lock.lock(); if (s_remoteIdInProgress == false) @@ -90,9 +89,8 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } else { - channelResult = winrt::make( + co_return winrt::make( nullptr, WPN_E_OUTSTANDING_CHANNEL_REQUEST, PushNotificationChannelStatus::CompletedFailure); - co_return channelResult; } } @@ -120,16 +118,24 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation progress(channelStatus); - PushNotificationChannelManager channelManager{}; - winrt::PushNotificationChannel pushChannelReceived{ nullptr }; - for (auto backOffTimeInSeconds = c_minBackoffSeconds; backOffTimeInSeconds <= c_maxBackoffSeconds * 2; backOffTimeInSeconds *= 2) { try { + PushNotificationChannelManager channelManager{}; + winrt::PushNotificationChannel pushChannelReceived{ nullptr }; + pushChannelReceived = co_await channelManager.CreatePushNotificationChannelForApplicationAsync(); - channelRequestResult = S_OK; - status = PushNotificationChannelStatus::CompletedSuccess; + + // Returns a com_ptr to the implementation type + auto pushChannel = + winrt::make_self(pushChannelReceived); + + co_return winrt::make( + winrt::make(pushChannelReceived), + S_OK, + PushNotificationChannelStatus::CompletedSuccess); + break; } catch (...) @@ -147,36 +153,17 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } else { - channelRequestResult = channelRequestException.code(); - status = PushNotificationChannelStatus::CompletedFailure; - break; + co_return winrt::make( + nullptr, + channelRequestException.code(), + PushNotificationChannelStatus::CompletedFailure); } } co_await winrt::resume_after(std::chrono::seconds(backOffTimeInSeconds)); } - - if (status == PushNotificationChannelStatus::CompletedSuccess) - { - // Returns a com_ptr to the implementation type - auto pushChannel = - winrt::make_self(pushChannelReceived); - - channelResult = winrt::make( - *(pushChannel.get()), - channelRequestResult, - status); - } - else if (status == PushNotificationChannelStatus::CompletedFailure) - { - channelResult = winrt::make( - nullptr, - channelRequestResult, - status); - } - - co_return channelResult; + co_return nullptr; } PushNotificationRegistrationToken PushNotificationManager::RegisterActivator(PushNotificationActivationInfo const& details) diff --git a/dev/PushNotifications/PushNotificationManager.h b/dev/PushNotifications/PushNotificationManager.h index 172c6edbcc..6104c4417d 100644 --- a/dev/PushNotifications/PushNotificationManager.h +++ b/dev/PushNotifications/PushNotificationManager.h @@ -10,7 +10,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation static Microsoft::Windows::PushNotifications::PushNotificationRegistrationToken RegisterActivator(Microsoft::Windows::PushNotifications::PushNotificationActivationInfo const& details); static void UnregisterActivator(Microsoft::Windows::PushNotifications::PushNotificationRegistrationToken const& token, Microsoft::Windows::PushNotifications::PushNotificationRegistrationOption const& option); - static winrt::Windows::Foundation::IAsyncOperationWithProgress CreateChannelAsync(winrt::guid remoteId); + static winrt::Windows::Foundation::IAsyncOperationWithProgress CreateChannelAsync(const winrt::guid &remoteId); private: static bool IsChannelRequestRetryable(const winrt::hresult& hrException); From 30109392fa4a7eeb49fb7c9cb62c4f74ffeefdbe Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Mon, 24 May 2021 12:03:00 -0700 Subject: [PATCH 19/53] Added more coverage with unit tests --- .../PushNotificationManager.cpp | 5 +- test/PushNotificationTests/APITests.cpp | 61 ++++++++++ .../PushNotificationsTestApp/main.cpp | 107 +++++++++++++++++- 3 files changed, 170 insertions(+), 3 deletions(-) diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp index 42c2d88ad8..8694e3551b 100644 --- a/dev/PushNotifications/PushNotificationManager.cpp +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -168,6 +168,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation PushNotificationRegistrationToken PushNotificationManager::RegisterActivator(PushNotificationActivationInfo const& details) { + THROW_HR_IF_NULL(E_INVALIDARG, details); THROW_HR_IF(E_INVALIDARG, details.TaskClsid() == winrt::guid()); THROW_HR_IF(E_INVALIDARG, !(WI_IsFlagSet(details.Option(), PushNotificationRegistrationOption::PushTrigger) || WI_IsFlagSet(details.Option(), PushNotificationRegistrationOption::ComActivator))); @@ -192,7 +193,6 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } else { - // Unregister background task here throw winrt::hresult_invalid_argument(L"RegisterActivator has different clsid registered."); } }; @@ -251,9 +251,10 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation void PushNotificationManager::UnregisterActivator(PushNotificationRegistrationToken const& token, PushNotificationRegistrationOption const& option) { - + THROW_HR_IF_NULL(E_INVALIDARG, token); if (WI_IsFlagSet(option, PushNotificationRegistrationOption::PushTrigger)) { + THROW_HR_IF_NULL(HRESULT_FROM_WIN32(ERROR_NOT_FOUND), token.TaskRegistration()); for (auto task : BackgroundTaskRegistration::AllTasks()) { if (task.Value().Name() == token.TaskRegistration().Name()) diff --git a/test/PushNotificationTests/APITests.cpp b/test/PushNotificationTests/APITests.cpp index d5cf728ab7..1e60d89fc6 100644 --- a/test/PushNotificationTests/APITests.cpp +++ b/test/PushNotificationTests/APITests.cpp @@ -164,6 +164,58 @@ namespace Test::PushNotifications WaitForEvent(event, m_failed); } + TEST_METHOD(RegisterActivatorNullDetails) + { + wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); + + // This is associated protocol for the MSIX installed app for launch. + // Use the ://path to define the component you want to test. + Uri launchUri{ c_testProtocolScheme_Packaged + L"://RegisterActivatorNullDetails" }; + auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); + VERIFY_IS_TRUE(launchResult); + + WaitForEvent(event, m_failed); + } + + TEST_METHOD(RegisterActivatorNullClsid) + { + wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); + + // This is associated protocol for the MSIX installed app for launch. + // Use the ://path to define the component you want to test. + Uri launchUri{ c_testProtocolScheme_Packaged + L"://RegisterActivatorNullClsid" }; + auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); + VERIFY_IS_TRUE(launchResult); + + WaitForEvent(event, m_failed); + } + + TEST_METHOD(UnregisterActivatorNullToken) + { + wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); + + // This is associated protocol for the MSIX installed app for launch. + // Use the ://path to define the component you want to test. + Uri launchUri{ c_testProtocolScheme_Packaged + L"://UnregisterActivatorNullToken" }; + auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); + VERIFY_IS_TRUE(launchResult); + + WaitForEvent(event, m_failed); + } + + TEST_METHOD(UnregisterActivatorNullBackgroundRegistration) + { + wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); + + // This is associated protocol for the MSIX installed app for launch. + // Use the ://path to define the component you want to test. + Uri launchUri{ c_testProtocolScheme_Packaged + L"://UnregisterActivatorNullBackgroundRegistration" }; + auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); + VERIFY_IS_TRUE(launchResult); + + WaitForEvent(event, m_failed); + } + TEST_METHOD(ActivatorTest) { wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); @@ -174,5 +226,14 @@ namespace Test::PushNotifications WaitForEvent(event, m_failed); } + TEST_METHOD(MultipleRegisterActivatorTest) + { + wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); + Uri launchUri{ c_testProtocolScheme_Packaged + L"://MultipleRegisterActivatorTest" }; + auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); + VERIFY_IS_TRUE(launchResult); + + WaitForEvent(event, m_failed); + } }; } diff --git a/test/TestApps/PushNotificationsTestApp/main.cpp b/test/TestApps/PushNotificationsTestApp/main.cpp index 816f5aab50..9938c61320 100644 --- a/test/TestApps/PushNotificationsTestApp/main.cpp +++ b/test/TestApps/PushNotificationsTestApp/main.cpp @@ -15,7 +15,8 @@ using namespace winrt::Windows::ApplicationModel::Background; // BackgroundTask enum UnitTest { channelRequestUsingNullRemoteId, channelRequestUsingRemoteId, multipleChannelRequestUsingSameRemoteId, - multipleChannelRequestUsingMultipleRemoteId, threeChannelRequestUsingSameRemoteId, activatorTest, + multipleChannelRequestUsingMultipleRemoteId, threeChannelRequestUsingSameRemoteId, activatorTest, registerActivatorNullDetails, + registerActivatorNullClsid, unregisterActivatorNullToken, unregisterActivatorNullBackgroundRegistration, multipleRegisterActivatorTest }; static std::map switchMapping; @@ -42,6 +43,11 @@ void initUnitTestMapping() switchMapping["MultipleChannelRequestUsingMultipleRemoteId"] = UnitTest::multipleChannelRequestUsingMultipleRemoteId; switchMapping["ThreeChannelRequestUsingSameRemoteId"] = UnitTest::threeChannelRequestUsingSameRemoteId; switchMapping["ActivatorTest"] = UnitTest::activatorTest; + switchMapping["RegisterActivatorNullDetails"] = UnitTest::registerActivatorNullDetails; + switchMapping["RegisterActivatorNullClsid"] = UnitTest::registerActivatorNullClsid; + switchMapping["UnregisterActivatorNullToken"] = UnitTest::unregisterActivatorNullToken; + switchMapping["UnregisterActivatorNullBackgroundRegistration"] = UnitTest::unregisterActivatorNullBackgroundRegistration; + switchMapping["MultipleRegisterActivatorTest"] = UnitTest::multipleRegisterActivatorTest; } bool ChannelRequestUsingNullRemoteId() @@ -145,6 +151,89 @@ bool ActivatorTest() return true; } +bool RegisterActivatorNullDetails() +{ + winrt::hresult hr = S_OK; + try + { + PushNotificationManager::RegisterActivator(nullptr); + } + catch (...) + { + auto registerActivatorException = hresult_error(to_hresult()); + hr = registerActivatorException.code(); + } + return hr == E_INVALIDARG; +} + +bool RegisterActivatorNullClsid() +{ + winrt::hresult hr = S_OK; + try + { + PushNotificationActivationInfo info( + PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator, + winrt::guid()); // same clsid as app manifest + PushNotificationManager::RegisterActivator(info); + } + catch (...) + { + auto registerActivatorException = hresult_error(to_hresult()); + hr = registerActivatorException.code(); + } + return hr == E_INVALIDARG; +} + +bool UnregisterActivatorNullToken() +{ + winrt::hresult hr = S_OK; + try + { + PushNotificationManager::UnregisterActivator(nullptr, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); + } + catch (...) + { + auto registerActivatorException = hresult_error(to_hresult()); + hr = registerActivatorException.code(); + } + return hr == E_INVALIDARG; +} + +bool UnregisterActivatorNullBackgroundRegistration() +{ + winrt::hresult hr = S_OK; + try + { + PushNotificationRegistrationToken badToken{ 0, nullptr }; + PushNotificationManager::UnregisterActivator(badToken, PushNotificationRegistrationOption::PushTrigger); + } + catch (...) + { + auto registerActivatorException = hresult_error(to_hresult()); + hr = registerActivatorException.code(); + } + return hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND); +} + +bool MultipleRegisterActivatorTest() +{ + winrt::hresult hr = S_OK; + try + { + PushNotificationActivationInfo info( + PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator, + c_fakeComServerId); // same clsid as app manifest + + appToken = PushNotificationManager::RegisterActivator(info); + } + catch (...) + { + auto registerActivatorException = hresult_error(to_hresult()); + hr = registerActivatorException.code(); + } + return hr == E_INVALIDARG; +} + bool runUnitTest(std::string unitTest) { switch (switchMapping[unitTest]) @@ -167,6 +256,21 @@ bool runUnitTest(std::string unitTest) case UnitTest::activatorTest: return ActivatorTest(); + case UnitTest::registerActivatorNullDetails: + return RegisterActivatorNullDetails(); + + case UnitTest::registerActivatorNullClsid: + return RegisterActivatorNullClsid(); + + case UnitTest::unregisterActivatorNullToken: + return UnregisterActivatorNullToken(); + + case UnitTest::unregisterActivatorNullBackgroundRegistration: + return UnregisterActivatorNullBackgroundRegistration(); + + case UnitTest::multipleRegisterActivatorTest: + return MultipleRegisterActivatorTest(); + default: return false; } @@ -186,6 +290,7 @@ void UnregisterClsid() ::CoRevokeClassObject(static_cast(fakeToken.Cookie())); PushNotificationManager::UnregisterActivator(fakeToken, PushNotificationRegistrationOption::PushTrigger); } + } int main() From 4873cdc5efcb4d6dfd7eb1e62c0f94570b61e6e8 Mon Sep 17 00:00:00 2001 From: Daniel Ayala Date: Mon, 24 May 2021 16:45:14 -0700 Subject: [PATCH 20/53] Changed global event args var with COM static store approach --- .../GetRawNotificationEventArgs.h | 21 +++++++++++++++---- .../PushNotificationBackgroundTask.cpp | 10 +++++++-- dev/PushNotifications/externs.h | 3 ++- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/dev/PushNotifications/GetRawNotificationEventArgs.h b/dev/PushNotifications/GetRawNotificationEventArgs.h index 81cfd44d48..de3c68f7dd 100644 --- a/dev/PushNotifications/GetRawNotificationEventArgs.h +++ b/dev/PushNotifications/GetRawNotificationEventArgs.h @@ -2,28 +2,41 @@ // Licensed under the MIT License. See LICENSE in the project root for license information. #pragma once #include "PushNotificationReceivedEventArgs.h" +#include #include "externs.h" static PCWSTR c_pushContractId = L"Windows.Push"; +using namespace winrt::Windows::ApplicationModel::Core; namespace winrt::Microsoft::Windows::PushNotifications { static winrt::Windows::Foundation::IInspectable Deserialize(winrt::Windows::Foundation::Uri const&) { { auto lock = g_lock.lock(); - if (g_activatedEventArgs) + + auto appProperties = CoreApplication::Properties(); + if (auto foundActivatedEventArgs = appProperties.TryLookup(ACTIVATED_EVENT_ARGS_KEY)) { - return g_activatedEventArgs; + return foundActivatedEventArgs.as(); } - THROW_HR_IF_NULL_MSG(E_UNEXPECTED, g_waitHandleForArgs, "PushNotificationManager::RegisterActivator has not been called."); + THROW_HR_IF_NULL_MSG(E_UNEXPECTED, g_waitHandleForArgs, "PushNotificationManager::RegisterActivator has not been called."); } if (WaitForSingleObject(g_waitHandleForArgs.get(), 1000) == WAIT_OBJECT_0) { auto lock = g_lock.lock(); - return g_activatedEventArgs; + + auto appProperties = CoreApplication::Properties(); + if (auto foundActivatedEventArgs = appProperties.TryLookup(ACTIVATED_EVENT_ARGS_KEY)) + { + return foundActivatedEventArgs.as(); + } + else + { + return nullptr; + } } winrt::throw_hresult(HRESULT_FROM_WIN32(ERROR_TIMEOUT)); } diff --git a/dev/PushNotifications/PushNotificationBackgroundTask.cpp b/dev/PushNotifications/PushNotificationBackgroundTask.cpp index fec7c8dd29..6ce7fc4c71 100644 --- a/dev/PushNotifications/PushNotificationBackgroundTask.cpp +++ b/dev/PushNotifications/PushNotificationBackgroundTask.cpp @@ -5,6 +5,8 @@ #include "PushNotificationBackgroundTask.h" #include +#include + #include "PushNotificationReceivedEventArgs.h" #include "externs.h" @@ -12,16 +14,20 @@ namespace winrt { using namespace Windows::ApplicationModel::Background; using namespace Microsoft::Windows::PushNotifications; + using namespace Windows::ApplicationModel::Core; } wil::unique_handle g_waitHandleForArgs; -winrt::PushNotificationReceivedEventArgs g_activatedEventArgs{ nullptr }; void PushNotificationBackgroundTask::Run(winrt::IBackgroundTaskInstance const& taskInstance) { { auto lock = g_lock.lock(); - g_activatedEventArgs = winrt::PushNotificationReceivedEventArgs::CreateFromBackgroundTaskInstance(taskInstance); + + auto appProperties = winrt::CoreApplication::Properties(); + winrt::PushNotificationReceivedEventArgs activatedEventArgs = winrt::PushNotificationReceivedEventArgs::CreateFromBackgroundTaskInstance(taskInstance); + appProperties.Insert(ACTIVATED_EVENT_ARGS_KEY, activatedEventArgs); } + SetEvent(g_waitHandleForArgs.get()); } diff --git a/dev/PushNotifications/externs.h b/dev/PushNotifications/externs.h index e0c7ddd8f8..cd5e797e9e 100644 --- a/dev/PushNotifications/externs.h +++ b/dev/PushNotifications/externs.h @@ -3,5 +3,6 @@ #include "PushNotificationReceivedEventArgs.h" extern wil::unique_handle g_waitHandleForArgs; -extern winrt::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs g_activatedEventArgs; extern wil::critical_section g_lock; + +const winrt::hstring ACTIVATED_EVENT_ARGS_KEY = L"GlobalActivatedEventArgs"; From ca810541d1028624e744f904ede5bfd7f27b1862 Mon Sep 17 00:00:00 2001 From: Daniel Ayala Date: Wed, 26 May 2021 09:04:56 -0700 Subject: [PATCH 21/53] Removed global lock --- .../GetRawNotificationEventArgs.h | 19 +++++++------------ .../PushNotificationBackgroundTask.cpp | 10 +++------- dev/PushNotifications/externs.h | 1 - 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/dev/PushNotifications/GetRawNotificationEventArgs.h b/dev/PushNotifications/GetRawNotificationEventArgs.h index de3c68f7dd..24d22a5717 100644 --- a/dev/PushNotifications/GetRawNotificationEventArgs.h +++ b/dev/PushNotifications/GetRawNotificationEventArgs.h @@ -12,23 +12,17 @@ namespace winrt::Microsoft::Windows::PushNotifications { static winrt::Windows::Foundation::IInspectable Deserialize(winrt::Windows::Foundation::Uri const&) { + auto appProperties = CoreApplication::Properties(); + if (auto foundActivatedEventArgs = appProperties.TryLookup(ACTIVATED_EVENT_ARGS_KEY)) { - auto lock = g_lock.lock(); - - auto appProperties = CoreApplication::Properties(); - if (auto foundActivatedEventArgs = appProperties.TryLookup(ACTIVATED_EVENT_ARGS_KEY)) - { - return foundActivatedEventArgs.as(); - } - - THROW_HR_IF_NULL_MSG(E_UNEXPECTED, g_waitHandleForArgs, "PushNotificationManager::RegisterActivator has not been called."); + return foundActivatedEventArgs.as(); } + THROW_HR_IF_NULL_MSG(E_UNEXPECTED, g_waitHandleForArgs, "PushNotificationManager::RegisterActivator has not been called."); + if (WaitForSingleObject(g_waitHandleForArgs.get(), 1000) == WAIT_OBJECT_0) { - auto lock = g_lock.lock(); - - auto appProperties = CoreApplication::Properties(); + appProperties = CoreApplication::Properties(); if (auto foundActivatedEventArgs = appProperties.TryLookup(ACTIVATED_EVENT_ARGS_KEY)) { return foundActivatedEventArgs.as(); @@ -38,6 +32,7 @@ namespace winrt::Microsoft::Windows::PushNotifications return nullptr; } } + winrt::throw_hresult(HRESULT_FROM_WIN32(ERROR_TIMEOUT)); } } diff --git a/dev/PushNotifications/PushNotificationBackgroundTask.cpp b/dev/PushNotifications/PushNotificationBackgroundTask.cpp index 6ce7fc4c71..bde0e86262 100644 --- a/dev/PushNotifications/PushNotificationBackgroundTask.cpp +++ b/dev/PushNotifications/PushNotificationBackgroundTask.cpp @@ -21,13 +21,9 @@ wil::unique_handle g_waitHandleForArgs; void PushNotificationBackgroundTask::Run(winrt::IBackgroundTaskInstance const& taskInstance) { - { - auto lock = g_lock.lock(); - - auto appProperties = winrt::CoreApplication::Properties(); - winrt::PushNotificationReceivedEventArgs activatedEventArgs = winrt::PushNotificationReceivedEventArgs::CreateFromBackgroundTaskInstance(taskInstance); - appProperties.Insert(ACTIVATED_EVENT_ARGS_KEY, activatedEventArgs); - } + auto appProperties = winrt::CoreApplication::Properties(); + winrt::PushNotificationReceivedEventArgs activatedEventArgs = winrt::PushNotificationReceivedEventArgs::CreateFromBackgroundTaskInstance(taskInstance); + appProperties.Insert(ACTIVATED_EVENT_ARGS_KEY, activatedEventArgs); SetEvent(g_waitHandleForArgs.get()); } diff --git a/dev/PushNotifications/externs.h b/dev/PushNotifications/externs.h index cd5e797e9e..968e6f46b5 100644 --- a/dev/PushNotifications/externs.h +++ b/dev/PushNotifications/externs.h @@ -3,6 +3,5 @@ #include "PushNotificationReceivedEventArgs.h" extern wil::unique_handle g_waitHandleForArgs; -extern wil::critical_section g_lock; const winrt::hstring ACTIVATED_EVENT_ARGS_KEY = L"GlobalActivatedEventArgs"; From 8e42ab412fd5a8afe2ab40aaaac42df8c88c9fb3 Mon Sep 17 00:00:00 2001 From: Sharath Manchala <10109130+sharath2727@users.noreply.github.com> Date: Thu, 27 May 2021 04:12:19 -0700 Subject: [PATCH 22/53] Support concurrency in channel request API --- .../PushNotificationManager.cpp | 47 ++++--------------- dev/PushNotifications/PushNotifications.idl | 2 +- 2 files changed, 10 insertions(+), 39 deletions(-) diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp index 8694e3551b..5a7b3f2f9a 100644 --- a/dev/PushNotifications/PushNotificationManager.cpp +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -30,8 +30,9 @@ wil::critical_section g_lock; namespace winrt::Microsoft::Windows::PushNotifications::implementation { - inline constexpr std::uint32_t c_maxBackoffSeconds{ 960 }; - inline constexpr std::uint32_t c_minBackoffSeconds{ 30 }; + inline constexpr auto c_maxBackoff{ 5min }; + inline constexpr auto c_initialBackoff{ 60s }; + inline constexpr auto c_backoffFactor{ 60s }; const HRESULT WNP_E_NOT_CONNECTED = (HRESULT)0x880403E8L; const HRESULT WNP_E_RECONNECTING = (HRESULT)0x880403E9L; @@ -59,47 +60,25 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation UINT32 packageFullNameLength = static_cast(ARRAYSIZE(packageFullName)); - const auto packagedProcessHResult = ::GetCurrentPackageFullName(&packageFullNameLength, packageFullName); + const auto packagedProcessError = ::GetCurrentPackageFullName(&packageFullNameLength, packageFullName); - if (packagedProcessHResult == APPMODEL_ERROR_NO_PACKAGE) + if (packagedProcessError == APPMODEL_ERROR_NO_PACKAGE) { return false; } - THROW_IF_WIN32_ERROR(packagedProcessHResult); + THROW_IF_WIN32_ERROR(packagedProcessError); return true; } winrt::IAsyncOperationWithProgress PushNotificationManager::CreateChannelAsync(const winrt::guid &remoteId) { - static bool s_remoteIdInProgress; - static wil::critical_section s_lock; - THROW_HR_IF(E_INVALIDARG, (remoteId == winrt::guid())); // API supports channel requests only for packaged applications for v0.8 version THROW_HR_IF(E_NOTIMPL, !IsPackagedProcess()); - { - auto lock = s_lock.lock(); - if (s_remoteIdInProgress == false) - { - s_remoteIdInProgress = true; - } - else - { - co_return winrt::make( - nullptr, WPN_E_OUTSTANDING_CHANNEL_REQUEST, PushNotificationChannelStatus::CompletedFailure); - } - } - - auto scopeExit = wil::scope_exit([&]() - { - auto lock = s_lock.lock(); - s_remoteIdInProgress = false; - }); - auto cancellation{ co_await winrt::get_cancellation_token() }; cancellation.enable_propagation(true); @@ -118,7 +97,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation progress(channelStatus); - for (auto backOffTimeInSeconds = c_minBackoffSeconds; backOffTimeInSeconds <= c_maxBackoffSeconds * 2; backOffTimeInSeconds *= 2) + for (auto backOffTime = c_initialBackoff; ; backOffTime += c_backoffFactor) { try { @@ -127,23 +106,17 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation pushChannelReceived = co_await channelManager.CreatePushNotificationChannelForApplicationAsync(); - // Returns a com_ptr to the implementation type - auto pushChannel = - winrt::make_self(pushChannelReceived); - co_return winrt::make( winrt::make(pushChannelReceived), S_OK, PushNotificationChannelStatus::CompletedSuccess); - break; } catch (...) { - auto channelRequestException = hresult_error(to_hresult(), take_ownership_from_abi); - if ((backOffTimeInSeconds <= c_maxBackoffSeconds) && IsChannelRequestRetryable(channelRequestException.code())) + if ((backOffTime <= c_maxBackoff) && IsChannelRequestRetryable(channelRequestException.code())) { channelStatus.extendedError = channelRequestException.code(); channelStatus.status = PushNotificationChannelStatus::InProgressRetry; @@ -160,10 +133,8 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } } - co_await winrt::resume_after(std::chrono::seconds(backOffTimeInSeconds)); + co_await winrt::resume_after(std::chrono::milliseconds(backOffTime)); } - - co_return nullptr; } PushNotificationRegistrationToken PushNotificationManager::RegisterActivator(PushNotificationActivationInfo const& details) diff --git a/dev/PushNotifications/PushNotifications.idl b/dev/PushNotifications/PushNotifications.idl index 517a9dea29..31d3f7eab6 100644 --- a/dev/PushNotifications/PushNotifications.idl +++ b/dev/PushNotifications/PushNotifications.idl @@ -104,7 +104,7 @@ namespace Microsoft.Windows.PushNotifications // More detailed error code in addition to the ChannelStatus state. HRESULT ExtendedError{ get; }; - // The Status of the ChannelComplete operation + // The Status of the CreateChannel operation PushNotificationChannelStatus Status { get; }; }; From cb6168f4bb2d66f79d35f1885cbb9ecbb8be47d2 Mon Sep 17 00:00:00 2001 From: Sharath Manchala <10109130+sharath2727@users.noreply.github.com> Date: Thu, 27 May 2021 04:41:51 -0700 Subject: [PATCH 23/53] Remove unused unittests --- test/PushNotificationTests/APITests.cpp | 13 ------------- .../TestApps/PushNotificationsTestApp/main.cpp | 18 +----------------- 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/test/PushNotificationTests/APITests.cpp b/test/PushNotificationTests/APITests.cpp index 1e60d89fc6..82a4ea60fa 100644 --- a/test/PushNotificationTests/APITests.cpp +++ b/test/PushNotificationTests/APITests.cpp @@ -142,19 +142,6 @@ namespace Test::PushNotifications WaitForEvent(event, m_failed); } - TEST_METHOD(ThreeChannelRequestUsingSameRemoteId) - { - wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); - - // This is associated protocol for the MSIX installed app for launch. - // Use the ://path to define the component you want to test. - Uri launchUri{ c_testProtocolScheme_Packaged + L"://ThreeChannelRequestUsingSameRemoteId" }; - auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); - VERIFY_IS_TRUE(launchResult); - - WaitForEvent(event, m_failed); - } - TEST_METHOD(BackgroundActivation) { wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); diff --git a/test/TestApps/PushNotificationsTestApp/main.cpp b/test/TestApps/PushNotificationsTestApp/main.cpp index 9938c61320..b69d38e6a9 100644 --- a/test/TestApps/PushNotificationsTestApp/main.cpp +++ b/test/TestApps/PushNotificationsTestApp/main.cpp @@ -15,7 +15,7 @@ using namespace winrt::Windows::ApplicationModel::Background; // BackgroundTask enum UnitTest { channelRequestUsingNullRemoteId, channelRequestUsingRemoteId, multipleChannelRequestUsingSameRemoteId, - multipleChannelRequestUsingMultipleRemoteId, threeChannelRequestUsingSameRemoteId, activatorTest, registerActivatorNullDetails, + multipleChannelRequestUsingMultipleRemoteId, activatorTest, registerActivatorNullDetails, registerActivatorNullClsid, unregisterActivatorNullToken, unregisterActivatorNullBackgroundRegistration, multipleRegisterActivatorTest }; @@ -41,7 +41,6 @@ void initUnitTestMapping() switchMapping["ChannelRequestUsingRemoteId"] = UnitTest::channelRequestUsingRemoteId; switchMapping["MultipleChannelRequestUsingSameRemoteId"] = UnitTest::multipleChannelRequestUsingSameRemoteId; switchMapping["MultipleChannelRequestUsingMultipleRemoteId"] = UnitTest::multipleChannelRequestUsingMultipleRemoteId; - switchMapping["ThreeChannelRequestUsingSameRemoteId"] = UnitTest::threeChannelRequestUsingSameRemoteId; switchMapping["ActivatorTest"] = UnitTest::activatorTest; switchMapping["RegisterActivatorNullDetails"] = UnitTest::registerActivatorNullDetails; switchMapping["RegisterActivatorNullClsid"] = UnitTest::registerActivatorNullClsid; @@ -115,18 +114,6 @@ bool MultipleChannelRequestUsingMultipleRemoteId() return channelOperationResult2 == WPN_E_OUTSTANDING_CHANNEL_REQUEST; } -bool ThreeChannelRequestUsingSameRemoteId() -{ - auto channelOperation1 = PushNotificationManager::CreateChannelAsync(remoteId1); - auto channelOperation2 = PushNotificationManager::CreateChannelAsync(remoteId2); - auto channelOperation3 = PushNotificationManager::CreateChannelAsync(remoteId3); - auto channelOperationResult2 = ChannelRequestHelper(channelOperation2); - auto channelOperationResult3 = ChannelRequestHelper(channelOperation3); - auto channelOperationResult1 = ChannelRequestHelper(channelOperation1); - - return channelOperationResult2 == WPN_E_OUTSTANDING_CHANNEL_REQUEST && channelOperationResult3 == WPN_E_OUTSTANDING_CHANNEL_REQUEST; -} - bool ActivatorTest() { PushNotificationManager::UnregisterActivator(appToken, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); @@ -250,9 +237,6 @@ bool runUnitTest(std::string unitTest) case UnitTest::multipleChannelRequestUsingMultipleRemoteId: return MultipleChannelRequestUsingMultipleRemoteId(); - case UnitTest::threeChannelRequestUsingSameRemoteId: - return ThreeChannelRequestUsingSameRemoteId(); - case UnitTest::activatorTest: return ActivatorTest(); From 3ff400d2856f45339a1ee9e9b4dfd5a865c5f574 Mon Sep 17 00:00:00 2001 From: Daniel Ayala Date: Thu, 27 May 2021 15:56:00 -0700 Subject: [PATCH 24/53] Addressed feedback in Background Activation impl code --- .../GetRawNotificationEventArgs.h | 9 +- .../PushNotificationActivationInfo.cpp | 5 +- .../PushNotificationActivationInfo.h | 5 +- .../PushNotificationBackgroundTask.cpp | 7 +- .../PushNotificationBackgroundTask.h | 5 +- .../PushNotificationChannel.cpp | 5 +- .../PushNotificationChannel.h | 5 +- .../PushNotificationCreateChannelResult.cpp | 5 +- .../PushNotificationCreateChannelResult.h | 5 +- .../PushNotificationManager.cpp | 108 +++++++++++------- .../PushNotificationManager.h | 5 +- .../PushNotificationReceivedEventArgs.cpp | 8 +- .../PushNotificationReceivedEventArgs.h | 7 +- .../PushNotificationRegistrationToken.cpp | 5 +- .../PushNotificationRegistrationToken.h | 5 +- dev/PushNotifications/PushNotifications.idl | 2 +- dev/PushNotifications/externs.h | 5 +- 17 files changed, 130 insertions(+), 66 deletions(-) diff --git a/dev/PushNotifications/GetRawNotificationEventArgs.h b/dev/PushNotifications/GetRawNotificationEventArgs.h index 24d22a5717..2ebead4687 100644 --- a/dev/PushNotifications/GetRawNotificationEventArgs.h +++ b/dev/PushNotifications/GetRawNotificationEventArgs.h @@ -1,5 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See LICENSE in the project root for license information. + #pragma once #include "PushNotificationReceivedEventArgs.h" #include @@ -12,17 +13,17 @@ namespace winrt::Microsoft::Windows::PushNotifications { static winrt::Windows::Foundation::IInspectable Deserialize(winrt::Windows::Foundation::Uri const&) { - auto appProperties = CoreApplication::Properties(); + /*auto appProperties = CoreApplication::Properties(); if (auto foundActivatedEventArgs = appProperties.TryLookup(ACTIVATED_EVENT_ARGS_KEY)) { return foundActivatedEventArgs.as(); } - THROW_HR_IF_NULL_MSG(E_UNEXPECTED, g_waitHandleForArgs, "PushNotificationManager::RegisterActivator has not been called."); + THROW_HR_IF_NULL_MSG(E_UNEXPECTED, g_waitHandleForArgs, "PushNotificationManager::RegisterActivator has not been called.");*/ - if (WaitForSingleObject(g_waitHandleForArgs.get(), 1000) == WAIT_OBJECT_0) + if (WaitForSingleObject(g_waitHandleForArgs.get(), 2000) == WAIT_OBJECT_0) { - appProperties = CoreApplication::Properties(); + auto appProperties = CoreApplication::Properties(); if (auto foundActivatedEventArgs = appProperties.TryLookup(ACTIVATED_EVENT_ARGS_KEY)) { return foundActivatedEventArgs.as(); diff --git a/dev/PushNotifications/PushNotificationActivationInfo.cpp b/dev/PushNotifications/PushNotificationActivationInfo.cpp index 358993eb8b..8cd18f6df9 100644 --- a/dev/PushNotifications/PushNotificationActivationInfo.cpp +++ b/dev/PushNotifications/PushNotificationActivationInfo.cpp @@ -1,4 +1,7 @@ -#include "pch.h" +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#include "pch.h" #include "PushNotificationActivationInfo.h" #include "Microsoft.Windows.PushNotifications.PushNotificationActivationInfo.g.cpp" diff --git a/dev/PushNotifications/PushNotificationActivationInfo.h b/dev/PushNotifications/PushNotificationActivationInfo.h index 01d377bb42..0cd6519d67 100644 --- a/dev/PushNotifications/PushNotificationActivationInfo.h +++ b/dev/PushNotifications/PushNotificationActivationInfo.h @@ -1,4 +1,7 @@ -#pragma once +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#pragma once #include "Microsoft.Windows.PushNotifications.PushNotificationActivationInfo.g.h" namespace winrt::Microsoft::Windows::PushNotifications::implementation diff --git a/dev/PushNotifications/PushNotificationBackgroundTask.cpp b/dev/PushNotifications/PushNotificationBackgroundTask.cpp index bde0e86262..7a8f1d41ee 100644 --- a/dev/PushNotifications/PushNotificationBackgroundTask.cpp +++ b/dev/PushNotifications/PushNotificationBackgroundTask.cpp @@ -1,4 +1,7 @@ -#pragma once +// 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" @@ -17,7 +20,7 @@ namespace winrt using namespace Windows::ApplicationModel::Core; } -wil::unique_handle g_waitHandleForArgs; +wil::unique_handle g_waitHandleForArgs = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); void PushNotificationBackgroundTask::Run(winrt::IBackgroundTaskInstance const& taskInstance) { diff --git a/dev/PushNotifications/PushNotificationBackgroundTask.h b/dev/PushNotifications/PushNotificationBackgroundTask.h index 331fb7f3af..9f763af7cb 100644 --- a/dev/PushNotifications/PushNotificationBackgroundTask.h +++ b/dev/PushNotifications/PushNotificationBackgroundTask.h @@ -1,4 +1,7 @@ -#include +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#include struct PushNotificationBackgroundTask : winrt::implements { diff --git a/dev/PushNotifications/PushNotificationChannel.cpp b/dev/PushNotifications/PushNotificationChannel.cpp index ac0b9abc8c..a1f0211d0c 100644 --- a/dev/PushNotifications/PushNotificationChannel.cpp +++ b/dev/PushNotifications/PushNotificationChannel.cpp @@ -1,4 +1,7 @@ -#include "pch.h" +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#include "pch.h" #include "PushNotificationChannel.h" #include "Microsoft.Windows.PushNotifications.PushNotificationChannel.g.cpp" #include diff --git a/dev/PushNotifications/PushNotificationChannel.h b/dev/PushNotifications/PushNotificationChannel.h index aa223c0d5f..83a4887798 100644 --- a/dev/PushNotifications/PushNotificationChannel.h +++ b/dev/PushNotifications/PushNotificationChannel.h @@ -1,4 +1,7 @@ -#pragma once +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#pragma once #include "Microsoft.Windows.PushNotifications.PushNotificationChannel.g.h" namespace winrt::Microsoft::Windows::PushNotifications::implementation diff --git a/dev/PushNotifications/PushNotificationCreateChannelResult.cpp b/dev/PushNotifications/PushNotificationCreateChannelResult.cpp index d9465b0a55..c8d2db6ab8 100644 --- a/dev/PushNotifications/PushNotificationCreateChannelResult.cpp +++ b/dev/PushNotifications/PushNotificationCreateChannelResult.cpp @@ -1,4 +1,7 @@ -#include "pch.h" +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#include "pch.h" #include "PushNotificationCreateChannelResult.h" #include "Microsoft.Windows.PushNotifications.PushNotificationCreateChannelResult.g.cpp" diff --git a/dev/PushNotifications/PushNotificationCreateChannelResult.h b/dev/PushNotifications/PushNotificationCreateChannelResult.h index b9ba9ef732..aef4483d3d 100644 --- a/dev/PushNotifications/PushNotificationCreateChannelResult.h +++ b/dev/PushNotifications/PushNotificationCreateChannelResult.h @@ -1,4 +1,7 @@ -#pragma once +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#pragma once #include "Microsoft.Windows.PushNotifications.PushNotificationCreateChannelResult.g.h" namespace winrt::Microsoft::Windows::PushNotifications::implementation diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp index 5a7b3f2f9a..43442b7dc8 100644 --- a/dev/PushNotifications/PushNotificationManager.cpp +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -1,4 +1,7 @@ -#include "pch.h" +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#include "pch.h" #include "PushNotificationManager.h" #include "Microsoft.Windows.PushNotifications.PushNotificationManager.g.cpp" @@ -26,8 +29,6 @@ namespace winrt using namespace Windows::Foundation; } -wil::critical_section g_lock; - namespace winrt::Microsoft::Windows::PushNotifications::implementation { inline constexpr auto c_maxBackoff{ 5min }; @@ -140,69 +141,87 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation PushNotificationRegistrationToken PushNotificationManager::RegisterActivator(PushNotificationActivationInfo const& details) { THROW_HR_IF_NULL(E_INVALIDARG, details); - THROW_HR_IF(E_INVALIDARG, details.TaskClsid() == winrt::guid()); - THROW_HR_IF(E_INVALIDARG, !(WI_IsFlagSet(details.Option(), PushNotificationRegistrationOption::PushTrigger) || WI_IsFlagSet(details.Option(), PushNotificationRegistrationOption::ComActivator))); GUID taskClsid = details.TaskClsid(); + THROW_HR_IF(E_INVALIDARG, taskClsid == GUID_NULL); + + auto registrationOption = details.Option(); + THROW_HR_IF(E_INVALIDARG, WI_AreAllFlagsClear(registrationOption, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator)); + DWORD cookie = 0; BackgroundTaskRegistration registeredTask = nullptr; BackgroundTaskBuilder builder = nullptr; - if (WI_IsFlagSet(details.Option(), PushNotificationRegistrationOption::PushTrigger)) + if (WI_IsFlagSet(registrationOption, PushNotificationRegistrationOption::PushTrigger)) { winrt::hstring taskClsidStr = winrt::to_hstring(taskClsid); + winrt::hstring backgroundTaskFullName = backgroundTaskName + taskClsidStr; + auto tasks = BackgroundTaskRegistration::AllTasks(); - bool taskRegistered = std::any_of(begin(tasks), end(tasks), - [&](auto&& task) - { - std::wstring backgroundTaskNameStr = task.Value().Name().c_str(); - if (backgroundTaskNameStr.find(backgroundTaskName) != std::wstring::npos) + bool taskRegistered = std::any_of(std::begin(tasks), std::end(tasks), + [&](auto&& task) { - if (backgroundTaskNameStr.find(taskClsidStr) != std::wstring::npos) + auto name = task.Value().Name(); + + if (std::wstring_view(name).substr(0, backgroundTaskName.size()) != backgroundTaskName) { - return true; + return false; } - else + + if (name == backgroundTaskFullName) { - throw winrt::hresult_invalid_argument(L"RegisterActivator has different clsid registered."); + return true; } - }; - return false; - }); + + throw winrt::hresult_invalid_argument(L"RegisterActivator has different clsid registered."); + }); if (!taskRegistered) { builder = BackgroundTaskBuilder(); - builder.Name(backgroundTaskName + taskClsidStr.c_str()); + builder.Name(backgroundTaskName + taskClsidStr); PushNotificationTrigger trigger{}; builder.SetTrigger(trigger); - auto builder5 = builder.try_as(); - if (IsPackagedProcess() && builder5) + if (!IsPackagedProcess()) { - builder5.SetTaskEntryPointClsid(taskClsid); - winrt::com_array conditions = details.GetConditions(); - for (auto condition : conditions) - { - builder.AddCondition(condition); - } + throw winrt::hresult_not_implemented(); } - else + + // In case the interface is not supported, let it throw. + auto builder5 = builder.as(); + builder5.SetTaskEntryPointClsid(taskClsid); + winrt::com_array conditions = details.GetConditions(); + for (auto condition : conditions) { - throw winrt::hresult_not_implemented(); + builder.AddCondition(condition); } } } - if (WI_IsFlagSet(details.Option(), PushNotificationRegistrationOption::ComActivator)) - { + bool registeredWithCom = false; + bool registeredWithBackgroundTask = false; + + auto scopeExitToCleanRegistrations = wil::scope_exit( + [&]() { - auto lock = g_lock.lock(); - // Define handle that will be set during background task execution - g_waitHandleForArgs = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); - THROW_HR_IF_NULL(E_UNEXPECTED, g_waitHandleForArgs); + if (registeredWithCom) + { + LOG_IF_FAILED(::CoRevokeClassObject(cookie)); + } + + if (registeredWithBackgroundTask) + { + registeredTask.Unregister(true); + } + } + ); + + if (WI_IsFlagSet(registrationOption, PushNotificationRegistrationOption::ComActivator)) + { + THROW_HR_IF_NULL(E_UNEXPECTED, g_waitHandleForArgs); THROW_IF_FAILED(::CoRegisterClassObject( taskClsid, @@ -210,14 +229,20 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie)); + + registeredWithCom = true; } if (builder) { registeredTask = builder.Register(); + registeredWithBackgroundTask = true; } - return PushNotificationRegistrationToken{ cookie, registeredTask }; + PushNotificationRegistrationToken token = { cookie, registeredTask }; + scopeExitToCleanRegistrations.release(); + + return token; } void PushNotificationManager::UnregisterActivator(PushNotificationRegistrationToken const& token, PushNotificationRegistrationOption const& option) @@ -225,14 +250,9 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation THROW_HR_IF_NULL(E_INVALIDARG, token); if (WI_IsFlagSet(option, PushNotificationRegistrationOption::PushTrigger)) { - THROW_HR_IF_NULL(HRESULT_FROM_WIN32(ERROR_NOT_FOUND), token.TaskRegistration()); - for (auto task : BackgroundTaskRegistration::AllTasks()) - { - if (task.Value().Name() == token.TaskRegistration().Name()) - { - task.Value().Unregister(true); - } - } + auto taskRegistration = token.TaskRegistration(); + THROW_HR_IF_NULL(HRESULT_FROM_WIN32(ERROR_NOT_FOUND), taskRegistration); + taskRegistration.Unregister(true); } if (WI_IsFlagSet(option, PushNotificationRegistrationOption::ComActivator) && token.Cookie()) diff --git a/dev/PushNotifications/PushNotificationManager.h b/dev/PushNotifications/PushNotificationManager.h index 6104c4417d..bfb8062f33 100644 --- a/dev/PushNotifications/PushNotificationManager.h +++ b/dev/PushNotifications/PushNotificationManager.h @@ -1,4 +1,7 @@ -#pragma once +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#pragma once #include "Microsoft.Windows.PushNotifications.PushNotificationManager.g.h" namespace winrt::Microsoft::Windows::PushNotifications::implementation diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp index 717c08aa42..8a256b5860 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp @@ -1,4 +1,7 @@ -#include "pch.h" +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#include "pch.h" #include #include @@ -36,7 +39,8 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation winrt::com_array PushNotificationReceivedEventArgs::Payload() { - return { m_rawNotification.data(), m_rawNotification.data() + (m_rawNotification.Length() * sizeof(uint8_t)) }; + auto rawNotificationData = m_rawNotification.data(); + return { rawNotificationData, rawNotificationData + (m_rawNotification.Length() * sizeof(uint8_t)) }; } winrt::BackgroundTaskDeferral PushNotificationReceivedEventArgs::GetDeferral() diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.h b/dev/PushNotifications/PushNotificationReceivedEventArgs.h index d55b632537..116900f845 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.h +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.h @@ -1,4 +1,7 @@ -#pragma once +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#pragma once #include "Microsoft.Windows.PushNotifications.PushNotificationReceivedEventArgs.g.h" namespace winrt::Microsoft::Windows::PushNotifications::implementation @@ -20,7 +23,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation private: const winrt::Windows::Storage::Streams::IBuffer m_rawNotification{}; - const winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance m_backgroundTaskInstance = nullptr; + const winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance m_backgroundTaskInstance{}; const winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs m_args = nullptr; }; } diff --git a/dev/PushNotifications/PushNotificationRegistrationToken.cpp b/dev/PushNotifications/PushNotificationRegistrationToken.cpp index 2a10782f54..d2b66c4d41 100644 --- a/dev/PushNotifications/PushNotificationRegistrationToken.cpp +++ b/dev/PushNotifications/PushNotificationRegistrationToken.cpp @@ -1,4 +1,7 @@ -#include "pch.h" +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#include "pch.h" #include "PushNotificationRegistrationToken.h" #include "Microsoft.Windows.PushNotifications.PushNotificationRegistrationToken.g.cpp" diff --git a/dev/PushNotifications/PushNotificationRegistrationToken.h b/dev/PushNotifications/PushNotificationRegistrationToken.h index 832b71a94f..4c8650f612 100644 --- a/dev/PushNotifications/PushNotificationRegistrationToken.h +++ b/dev/PushNotifications/PushNotificationRegistrationToken.h @@ -1,4 +1,7 @@ -#pragma once +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#pragma once #include "Microsoft.Windows.PushNotifications.PushNotificationRegistrationToken.g.h" namespace winrt::Microsoft::Windows::PushNotifications::implementation diff --git a/dev/PushNotifications/PushNotifications.idl b/dev/PushNotifications/PushNotifications.idl index 31d3f7eab6..cf43f67a0a 100644 --- a/dev/PushNotifications/PushNotifications.idl +++ b/dev/PushNotifications/PushNotifications.idl @@ -37,7 +37,7 @@ namespace Microsoft.Windows.PushNotifications runtimeclass PushNotificationActivationInfo { // Initialize using a RegistrationOption and optionally defined parameters like manifest defined activatorId - // 1) If option = PushTrigger is specified, only the Push Trigger will be Registered with Background Infra + // 1) If option = PushTrigger is specified, only the Push Trigger will be Registered with Background Infrastructure // 2) If option = ComActivator is specified, the Project Reunion Background Task component will be Registered as an InProc COM server PushNotificationActivationInfo(PushNotificationRegistrationOption option, Guid taskClsid); diff --git a/dev/PushNotifications/externs.h b/dev/PushNotifications/externs.h index 968e6f46b5..91854e85d9 100644 --- a/dev/PushNotifications/externs.h +++ b/dev/PushNotifications/externs.h @@ -1,4 +1,7 @@ -#pragma once +// 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 "PushNotificationReceivedEventArgs.h" From 001f3bc731f5190b29acf9311ab32cd4200e3602 Mon Sep 17 00:00:00 2001 From: Daniel Ayala Date: Fri, 28 May 2021 15:23:20 -0700 Subject: [PATCH 25/53] Addressed corner case where we returned nullptr if the task was already registered --- dev/PushNotifications/GetRawNotificationEventArgs.h | 8 -------- dev/PushNotifications/PushNotificationManager.cpp | 11 +++++++---- .../PushNotificationRegistrationToken.cpp | 4 ++-- .../PushNotificationRegistrationToken.h | 6 +++--- dev/PushNotifications/PushNotifications.idl | 4 ++-- 5 files changed, 14 insertions(+), 19 deletions(-) diff --git a/dev/PushNotifications/GetRawNotificationEventArgs.h b/dev/PushNotifications/GetRawNotificationEventArgs.h index 2ebead4687..2d790dc016 100644 --- a/dev/PushNotifications/GetRawNotificationEventArgs.h +++ b/dev/PushNotifications/GetRawNotificationEventArgs.h @@ -13,14 +13,6 @@ namespace winrt::Microsoft::Windows::PushNotifications { static winrt::Windows::Foundation::IInspectable Deserialize(winrt::Windows::Foundation::Uri const&) { - /*auto appProperties = CoreApplication::Properties(); - if (auto foundActivatedEventArgs = appProperties.TryLookup(ACTIVATED_EVENT_ARGS_KEY)) - { - return foundActivatedEventArgs.as(); - } - - THROW_HR_IF_NULL_MSG(E_UNEXPECTED, g_waitHandleForArgs, "PushNotificationManager::RegisterActivator has not been called.");*/ - if (WaitForSingleObject(g_waitHandleForArgs.get(), 2000) == WAIT_OBJECT_0) { auto appProperties = CoreApplication::Properties(); diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp index 43442b7dc8..0fb93419d5 100644 --- a/dev/PushNotifications/PushNotificationManager.cpp +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -149,7 +149,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation THROW_HR_IF(E_INVALIDARG, WI_AreAllFlagsClear(registrationOption, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator)); DWORD cookie = 0; - BackgroundTaskRegistration registeredTask = nullptr; + IBackgroundTaskRegistration registeredTask = nullptr; BackgroundTaskBuilder builder = nullptr; if (WI_IsFlagSet(registrationOption, PushNotificationRegistrationOption::PushTrigger)) @@ -158,7 +158,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation winrt::hstring backgroundTaskFullName = backgroundTaskName + taskClsidStr; auto tasks = BackgroundTaskRegistration::AllTasks(); - bool taskRegistered = std::any_of(std::begin(tasks), std::end(tasks), + bool isTaskRegistered = std::any_of(std::begin(tasks), std::end(tasks), [&](auto&& task) { auto name = task.Value().Name(); @@ -170,13 +170,14 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation if (name == backgroundTaskFullName) { + registeredTask = task.Value(); return true; } throw winrt::hresult_invalid_argument(L"RegisterActivator has different clsid registered."); }); - if (!taskRegistered) + if (!isTaskRegistered) { builder = BackgroundTaskBuilder(); builder.Name(backgroundTaskName + taskClsidStr); @@ -211,6 +212,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation LOG_IF_FAILED(::CoRevokeClassObject(cookie)); } + // Clean the task registration only if it was created during this call if (registeredWithBackgroundTask) { registeredTask.Unregister(true); @@ -235,7 +237,8 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation if (builder) { - registeredTask = builder.Register(); + auto registeredTaskFromBuilder = builder.Register(); + registeredTask = registeredTaskFromBuilder.as(); registeredWithBackgroundTask = true; } diff --git a/dev/PushNotifications/PushNotificationRegistrationToken.cpp b/dev/PushNotifications/PushNotificationRegistrationToken.cpp index d2b66c4d41..ed6581c0bc 100644 --- a/dev/PushNotifications/PushNotificationRegistrationToken.cpp +++ b/dev/PushNotifications/PushNotificationRegistrationToken.cpp @@ -9,14 +9,14 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { - PushNotificationRegistrationToken::PushNotificationRegistrationToken(uint64_t const& cookie, winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration const& taskRegistration): m_cookie(cookie), m_taskRegistration(taskRegistration) { } + PushNotificationRegistrationToken::PushNotificationRegistrationToken(uint64_t const& cookie, winrt::Windows::ApplicationModel::Background::IBackgroundTaskRegistration const& taskRegistration): m_cookie(cookie), m_taskRegistration(taskRegistration) { } uint64_t PushNotificationRegistrationToken::Cookie() { return m_cookie; } - winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration PushNotificationRegistrationToken::TaskRegistration() + winrt::Windows::ApplicationModel::Background::IBackgroundTaskRegistration PushNotificationRegistrationToken::TaskRegistration() { return m_taskRegistration; } diff --git a/dev/PushNotifications/PushNotificationRegistrationToken.h b/dev/PushNotifications/PushNotificationRegistrationToken.h index 4c8650f612..571917d374 100644 --- a/dev/PushNotifications/PushNotificationRegistrationToken.h +++ b/dev/PushNotifications/PushNotificationRegistrationToken.h @@ -8,13 +8,13 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { struct PushNotificationRegistrationToken : PushNotificationRegistrationTokenT { - PushNotificationRegistrationToken(uint64_t const& cookie, winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration const& taskRegistration); + PushNotificationRegistrationToken(uint64_t const& cookie, winrt::Windows::ApplicationModel::Background::IBackgroundTaskRegistration const& taskRegistration); uint64_t Cookie(); - winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration TaskRegistration(); + winrt::Windows::ApplicationModel::Background::IBackgroundTaskRegistration TaskRegistration(); private: const uint64_t m_cookie; - const winrt::Windows::ApplicationModel::Background::BackgroundTaskRegistration m_taskRegistration; + const winrt::Windows::ApplicationModel::Background::IBackgroundTaskRegistration m_taskRegistration; }; } namespace winrt::Microsoft::Windows::PushNotifications::factory_implementation diff --git a/dev/PushNotifications/PushNotifications.idl b/dev/PushNotifications/PushNotifications.idl index cf43f67a0a..2926f90c09 100644 --- a/dev/PushNotifications/PushNotifications.idl +++ b/dev/PushNotifications/PushNotifications.idl @@ -113,13 +113,13 @@ namespace Microsoft.Windows.PushNotifications { PushNotificationRegistrationToken( UInt64 cookie, - Windows.ApplicationModel.Background.BackgroundTaskRegistration taskRegistration); + Windows.ApplicationModel.Background.IBackgroundTaskRegistration taskRegistration); // The cookie from CoRegisterClassObject UInt64 Cookie{ get; }; // The Registration token for the Push Trigger - Windows.ApplicationModel.Background.BackgroundTaskRegistration TaskRegistration { get; }; + Windows.ApplicationModel.Background.IBackgroundTaskRegistration TaskRegistration { get; }; }; [experimental] From f60056e66a660057619c7324145a882183bd42a7 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Tue, 1 Jun 2021 13:05:02 -0700 Subject: [PATCH 26/53] Removed global events -> parent/child testing with exit code --- test/PushNotificationTests/APITests.cpp | 194 ++++++++---------- test/PushNotificationTests/Shared.cpp | 111 ---------- test/PushNotificationTests/Shared.h | 12 -- test/PushNotificationTests/pch.h | 2 + .../PushNotificationsDemoApp/main.cpp | 3 +- .../PushNotificationsTestApp/main.cpp | 29 +-- test/inc/TestDef.h | 6 +- 7 files changed, 96 insertions(+), 261 deletions(-) diff --git a/test/PushNotificationTests/APITests.cpp b/test/PushNotificationTests/APITests.cpp index 82a4ea60fa..7b90a432c7 100644 --- a/test/PushNotificationTests/APITests.cpp +++ b/test/PushNotificationTests/APITests.cpp @@ -3,8 +3,8 @@ #include "pch.h" #include -#include "Shared.h" #include "MockBackgroundTaskInstance.h" +#include "Shared.h" using namespace WEX::Common; using namespace WEX::Logging; @@ -24,10 +24,12 @@ namespace Test::PushNotifications { private: wil::unique_event m_failed; + HANDLE m_process; + winrt::com_ptr m_testAppLauncher; - const std::wstring c_testPackageFile = g_deploymentDir + L"PushNotificationsTestAppPackage_1.0.0.0_x64.msixbundle"; - const std::wstring c_testPackageCertFile = g_deploymentDir + L"PushNotificationsTestAppPackage_1.0.0.0_x64.cer"; - const std::wstring c_testPackageFullName = L"PushNotificationsTestAppPackage_1.0.0.0_x64__8wekyb3d8bbwe"; + //const std::wstring c_testPackageFile = g_deploymentDir + L"PushNotificationsTestAppPackage.msix"; + //const std::wstring c_testPackageFullName = L"PushNotificationsTestAppPackage_1.0.0.0_" PROJECTREUNION_TEST_PACKAGE_DDLM_ARCHITECTURE L"__8wekyb3d8bbwe"; + //const std::wstring c_testVCLibsPackageFile = g_deploymentDir + L"VCLibs.appx"; public: BEGIN_TEST_CLASS(APITests) @@ -36,36 +38,56 @@ namespace Test::PushNotifications TEST_CLASS_PROPERTY(L"RunAs:Class", L"RestrictedUser") END_TEST_CLASS() + static std::wstring GetDeploymentDir() + { + WEX::Common::String testDeploymentDir; + WEX::TestExecution::RuntimeParameters::TryGetValue(L"TestDeploymentDir", testDeploymentDir); + return reinterpret_cast(testDeploymentDir.GetBuffer()); + } + + static std::filesystem::path GetTestVCLibsPackageFile() + { + auto filename{ std::filesystem::path(GetDeploymentDir()) }; + filename /= L"VCLibs.appx"; + return filename; + } + + static std::filesystem::path GetTestPackageFile() + { + auto filename{ std::filesystem::path(GetDeploymentDir()) }; + filename /= L"PushNotificationsTestAppPackage.msix"; + return filename; + } + + static std::wstring GetTestPackageFullName() + { + return L"PushNotificationsTestAppPackage_1.0.0.0_" PROJECTREUNION_TEST_PACKAGE_DDLM_ARCHITECTURE L"__8wekyb3d8bbwe"; + } + TEST_CLASS_SETUP(ClassInit) { try { - InstallPackage(c_testVCLibsPackageFile); + TP::AddPackage_ProjectReunionFramework(); + InstallPackage(GetTestVCLibsPackageFile()); + InstallPackage(GetTestPackageFile()); } catch (...) { return false; } - TP::AddPackage_ProjectReunionFramework(); - try - { - InstallPackage(c_testPackageFile); - } - catch (...) - { - return false; - } + m_testAppLauncher = winrt::create_instance(CLSID_ApplicationActivationManager, CLSCTX_ALL); + VERIFY_IS_NOT_NULL(m_testAppLauncher); return true; } TEST_CLASS_CLEANUP(ClassUninit) { - TP::RemovePackage_ProjectReunionFramework(); - try { - UninstallPackage(c_testPackageFullName); + TP::RemovePackage_ProjectReunionFramework(); + UninstallPackage(GetTestPackageFullName()); } catch (...) { @@ -77,9 +99,6 @@ namespace Test::PushNotifications TEST_METHOD_SETUP(MethodInit) { VERIFY_IS_TRUE(TP::IsPackageRegistered_ProjectReunionFramework()); - - m_failed = CreateTestEvent(c_testFailureEventName); - return true; } @@ -87,140 +106,89 @@ namespace Test::PushNotifications { VERIFY_IS_TRUE(TP::IsPackageRegistered_ProjectReunionFramework()); + if (m_process) + { + VERIFY_IS_TRUE(CloseHandle(m_process)); + } return true; } - TEST_METHOD(ChannelRequestUsingNullRemoteId) + void RunTest(const PCWSTR& testName) { - wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); + DWORD pid; + VERIFY_SUCCEEDED(m_testAppLauncher.get()->ActivateApplication(L"PushNotificationsTestAppPackage_8wekyb3d8bbwe!App", testName, AO_NONE, &pid)); + VERIFY_IS_NOT_NULL(pid); + + m_process = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid); + VERIFY_IS_NOT_NULL(m_process); - // This is associated protocol for the MSIX installed app for launch. - // Use the ://path to define the component you want to test. - Uri launchUri{ c_testProtocolScheme_Packaged + L"://ChannelRequestUsingNullRemoteId" }; - auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); - VERIFY_IS_TRUE(launchResult); + VERIFY_ARE_EQUAL(WaitForSingleObject(m_process, 3000), WAIT_OBJECT_0); - WaitForEvent(event, m_failed); + DWORD exitCode; + VERIFY_IS_TRUE(GetExitCodeProcess(m_process, &exitCode)); + VERIFY_ARE_EQUAL(exitCode, 0); + + VERIFY_IS_TRUE(CloseHandle(m_process)); + m_process = nullptr; } - TEST_METHOD(ChannelRequestUsingRemoteId) + TEST_METHOD(BackgroundActivation) { - wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); + RunTest(nullptr); // Just need to launch. - // This is associated protocol for the MSIX installed app for launch. - // Use the ://path to define the component you want to test. - Uri launchUri{ c_testProtocolScheme_Packaged + L"://ChannelRequestUsingRemoteId" }; - auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); - VERIFY_IS_TRUE(launchResult); - - WaitForEvent(event, m_failed); + auto LocalBackgroundTask = winrt::create_instance(c_comServerId, CLSCTX_ALL); + auto mockBackgroundTaskInstance = winrt::make(); + VERIFY_NO_THROW(LocalBackgroundTask.Run(mockBackgroundTaskInstance)); } - TEST_METHOD(MultipleChannelRequestUsingSameRemoteId) + TEST_METHOD(ChannelRequestUsingNullRemoteId) { - wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); + RunTest(L"ChannelRequestUsingNullRemoteId"); + } - // This is associated protocol for the MSIX installed app for launch. - // Use the ://path to define the component you want to test. - Uri launchUri{ c_testProtocolScheme_Packaged + L"://MultipleChannelRequestUsingSameRemoteId" }; - auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); - VERIFY_IS_TRUE(launchResult); + TEST_METHOD(ChannelRequestUsingRemoteId) + { + RunTest(L"ChannelRequestUsingRemoteId"); + } - WaitForEvent(event, m_failed); + /*TEST_METHOD(MultipleChannelRequestUsingSameRemoteId) + { + RunTest(L"MultipleChannelRequestUsingSameRemoteId"); } TEST_METHOD(MultipleChannelRequestUsingMultipleRemoteId) { - wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); - - // This is associated protocol for the MSIX installed app for launch. - // Use the ://path to define the component you want to test. - Uri launchUri{ c_testProtocolScheme_Packaged + L"://MultipleChannelRequestUsingMultipleRemoteId" }; - auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); - VERIFY_IS_TRUE(launchResult); - - WaitForEvent(event, m_failed); - } + RunTest(L"MultipleChannelRequestUsingMultipleRemoteId"); + }*/ - TEST_METHOD(BackgroundActivation) + TEST_METHOD(ActivatorTest) { - wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); - auto LocalBackgroundTask = winrt::create_instance(c_comServerId, CLSCTX_ALL); - auto mockBackgroundTaskInstance = winrt::make(); - LocalBackgroundTask.Run(mockBackgroundTaskInstance); - WaitForEvent(event, m_failed); + RunTest(L"ActivatorTest"); } TEST_METHOD(RegisterActivatorNullDetails) { - wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); - - // This is associated protocol for the MSIX installed app for launch. - // Use the ://path to define the component you want to test. - Uri launchUri{ c_testProtocolScheme_Packaged + L"://RegisterActivatorNullDetails" }; - auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); - VERIFY_IS_TRUE(launchResult); - - WaitForEvent(event, m_failed); + RunTest(L"RegisterActivatorNullDetails"); } TEST_METHOD(RegisterActivatorNullClsid) { - wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); - - // This is associated protocol for the MSIX installed app for launch. - // Use the ://path to define the component you want to test. - Uri launchUri{ c_testProtocolScheme_Packaged + L"://RegisterActivatorNullClsid" }; - auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); - VERIFY_IS_TRUE(launchResult); - - WaitForEvent(event, m_failed); + RunTest(L"RegisterActivatorNullClsid"); } TEST_METHOD(UnregisterActivatorNullToken) { - wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); - - // This is associated protocol for the MSIX installed app for launch. - // Use the ://path to define the component you want to test. - Uri launchUri{ c_testProtocolScheme_Packaged + L"://UnregisterActivatorNullToken" }; - auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); - VERIFY_IS_TRUE(launchResult); - - WaitForEvent(event, m_failed); + RunTest(L"UnregisterActivatorNullToken"); } TEST_METHOD(UnregisterActivatorNullBackgroundRegistration) { - wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); - - // This is associated protocol for the MSIX installed app for launch. - // Use the ://path to define the component you want to test. - Uri launchUri{ c_testProtocolScheme_Packaged + L"://UnregisterActivatorNullBackgroundRegistration" }; - auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); - VERIFY_IS_TRUE(launchResult); - - WaitForEvent(event, m_failed); - } - - TEST_METHOD(ActivatorTest) - { - wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); - Uri launchUri{ c_testProtocolScheme_Packaged + L"://ActivatorTest" }; - auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); - VERIFY_IS_TRUE(launchResult); - - WaitForEvent(event, m_failed); + RunTest(L"UnregisterActivatorNullBackgroundRegistration"); } TEST_METHOD(MultipleRegisterActivatorTest) { - wil::unique_event event = CreateTestEvent(c_testProtocolScheme_Packaged); - Uri launchUri{ c_testProtocolScheme_Packaged + L"://MultipleRegisterActivatorTest" }; - auto launchResult = Launcher::LaunchUriAsync(launchUri).get(); - VERIFY_IS_TRUE(launchResult); - - WaitForEvent(event, m_failed); + RunTest(L"MultipleRegisterActivatorTest"); } }; } diff --git a/test/PushNotificationTests/Shared.cpp b/test/PushNotificationTests/Shared.cpp index 059d69489f..6d8d1bb28c 100644 --- a/test/PushNotificationTests/Shared.cpp +++ b/test/PushNotificationTests/Shared.cpp @@ -19,59 +19,6 @@ using namespace winrt::Windows::System; namespace Test::PushNotifications { - StorageFile CreateDocFile(std::wstring filename) - { - return KnownFolders::DocumentsLibrary().CreateFileAsync(filename, - CreationCollisionOption::OpenIfExists).get(); - } - - StorageFile OpenDocFile(std::wstring filename) - { - return KnownFolders::DocumentsLibrary().GetFileAsync(filename).get(); - } - - wil::unique_handle Execute(const std::wstring& command, const std::wstring& args, - const std::wstring& directory) - { - SHELLEXECUTEINFO ei{}; - ei.cbSize = sizeof(SHELLEXECUTEINFO); - ei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_DOENVSUBST; - ei.lpFile = command.c_str(); - ei.lpParameters = args.c_str(); - ei.lpDirectory = directory.c_str(); - - if (!ShellExecuteEx(&ei)) - { - auto lastError = GetLastError(); - VERIFY_WIN32_SUCCEEDED(lastError); - } - - wil::unique_handle process{ ei.hProcess }; - return process; - } - - void RunCertUtil(const std::wstring& path, bool removeCert) - { - std::wstring action = (removeCert ? L"-delstore" : L"-addstore"); - std::wstring args{ action + L" TrustedPeople " + path }; - // VERIFY_ARE_NOT_EQUAL(args, args); - auto process = Execute(L"%SystemRoot%\\system32\\certutil.exe", - args, g_deploymentDir); - - // Wait for the cer to be installed. - auto waitResult = WaitForSingleObject(process.get(), c_phaseTimeout); - if (waitResult != WAIT_OBJECT_0) - { - if (waitResult == WAIT_FAILED) VERIFY_WIN32_SUCCEEDED(GetLastError()); - VERIFY_ARE_EQUAL(waitResult, WAIT_OBJECT_0); - } - - // Make sure the exitcode for the tool is success. - DWORD exitCode{}; - THROW_IF_WIN32_BOOL_FALSE(GetExitCodeProcess(process.get(), &exitCode)); - VERIFY_ARE_EQUAL(exitCode, 0); - } - void InstallPackage(const std::wstring& packagePath) { // Deploy packaged app to register handler through the manifest. @@ -94,62 +41,4 @@ namespace Test::PushNotifications auto errorCode = result.ExtendedErrorCode(); VERIFY_SUCCEEDED(errorCode, errorText.c_str()); } - - wil::unique_event CreateTestEvent(const std::wstring& eventName) - { - bool alreadyExists = false; - SECURITY_ATTRIBUTES attributes = {}; - wil::unique_hlocal_security_descriptor descriptor; - - // Grant access to world and appcontainer. - THROW_IF_WIN32_BOOL_FALSE(ConvertStringSecurityDescriptorToSecurityDescriptor( - L"D:(A;;GA;;;WD)(A;;GA;;;AC)", SDDL_REVISION_1, &descriptor, nullptr)); - attributes.nLength = sizeof(SECURITY_ATTRIBUTES); - attributes.lpSecurityDescriptor = descriptor.get(); - - wil::unique_event event; - event.create(wil::EventOptions::None, eventName.c_str(), &attributes, &alreadyExists); - return event; - } - - void WaitForEvent(const wil::unique_event& successEvent, const wil::unique_event& failedEvent) - { - HANDLE waitEvents[2] = { successEvent.get(), failedEvent.get() }; - auto waitResult = WaitForMultipleObjects(_countof(waitEvents), waitEvents, FALSE, - c_phaseTimeout); - - // If waitResult == failureEventIndex, it means the remote test process signaled a - // failure event while we were waiting for a different event. - auto failureEventIndex = WAIT_OBJECT_0 + 1; - VERIFY_ARE_NOT_EQUAL(waitResult, failureEventIndex); - - VERIFY_ARE_NOT_EQUAL(waitResult, WAIT_TIMEOUT); - if (waitResult == WAIT_FAILED) - { - auto lastError = GetLastError(); - VERIFY_WIN32_FAILED(lastError); - } - - successEvent.ResetEvent(); - failedEvent.ResetEvent(); - } - - const std::wstring GetDeploymentDir() - { - WEX::Common::String testDeploymentDir; - WEX::TestExecution::RuntimeParameters::TryGetValue(L"TestDeploymentDir", testDeploymentDir); - return reinterpret_cast(testDeploymentDir.GetBuffer()); - } - - void WriteContentFile(std::wstring filename) - { - auto file = CreateDocFile(filename); - FileIO::WriteTextAsync(file, L"Hello, World!").get(); - } - - void DeleteContentFile(std::wstring filename) - { - auto file = CreateDocFile(filename); - file.DeleteAsync().get(); - } } diff --git a/test/PushNotificationTests/Shared.h b/test/PushNotificationTests/Shared.h index 5128b67ab1..428ac939ce 100644 --- a/test/PushNotificationTests/Shared.h +++ b/test/PushNotificationTests/Shared.h @@ -4,18 +4,6 @@ namespace Test::PushNotifications { - winrt::Windows::Storage::StorageFile CreateDocFile(std::wstring filename); - winrt::Windows::Storage::StorageFile OpenDocFile(std::wstring filename); - wil::unique_handle Execute(const std::wstring& command, const std::wstring& args, - const std::wstring& directory); - void RunCertUtil(const std::wstring& path, bool removeCert = false); void InstallPackage(const std::wstring& packagePath); void UninstallPackage(const std::wstring& packageFullName); - wil::unique_event CreateTestEvent(const std::wstring& eventName); - void WaitForEvent(const wil::unique_event& successEvent, const wil::unique_event& failedEvent); - const std::wstring GetDeploymentDir(); - void WriteContentFile(std::wstring filename); - void DeleteContentFile(std::wstring filename); - - const std::wstring g_deploymentDir = GetDeploymentDir(); } diff --git a/test/PushNotificationTests/pch.h b/test/PushNotificationTests/pch.h index 7c2becaf82..60112bed3f 100644 --- a/test/PushNotificationTests/pch.h +++ b/test/PushNotificationTests/pch.h @@ -33,4 +33,6 @@ #include #include #include +#include + namespace TP = ::Test::Packages; diff --git a/test/TestApps/PushNotificationsDemoApp/main.cpp b/test/TestApps/PushNotificationsDemoApp/main.cpp index d0e50cf920..654a9bf063 100644 --- a/test/TestApps/PushNotificationsDemoApp/main.cpp +++ b/test/TestApps/PushNotificationsDemoApp/main.cpp @@ -22,7 +22,8 @@ char buf[SIZE]; winrt::Windows::Foundation::IAsyncOperation RequestChannelAsync() { - // Register the AAD RemoteIdentifier for the App to receive Push + // To obtain an AAD RemoteIdentifier for your app, + // follow the instructions on https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app auto channelOperation = PushNotificationManager::CreateChannelAsync( winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2")); diff --git a/test/TestApps/PushNotificationsTestApp/main.cpp b/test/TestApps/PushNotificationsTestApp/main.cpp index b69d38e6a9..cd3bd56944 100644 --- a/test/TestApps/PushNotificationsTestApp/main.cpp +++ b/test/TestApps/PushNotificationsTestApp/main.cpp @@ -280,40 +280,27 @@ void UnregisterClsid() int main() { initUnitTestMapping(); - bool output = false; + bool failed = false; auto scope_exit = wil::scope_exit([&] { UnregisterClsid(); - if (output) - { - // Signal TAEF that protocol was activated and valid. - signalPhase(c_testProtocolScheme_Packaged); - } - else - { - // Signal TAEF that the test failed - signalPhase(c_testFailureEventName); - } }); PushNotificationActivationInfo info( PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator, - winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2")); // same clsid as app manifest + winrt::guid(c_comServerId)); // same clsid as app manifest appToken = PushNotificationManager::RegisterActivator(info); auto args = AppInstance::GetCurrent().GetActivatedEventArgs(); auto kind = args.Kind(); - if (kind == ExtendedActivationKind::Protocol) + if (kind == ExtendedActivationKind::Launch) { - auto protocolArgs = args.Data().as(); - Uri actualUri = protocolArgs.Uri(); - std::string unitTest = winrt::to_string(actualUri.Host()); - + auto launchArgs = args.Data().as(); + std::string unitTest = to_string(launchArgs.Arguments()); std::cout << unitTest << std::endl; - // Switch on this variable to run specific components (uri://ComponentToTest) - output = runUnitTest(unitTest); + failed = runUnitTest(unitTest); } else if (kind == ExtendedActivationKind::Push) { @@ -321,8 +308,8 @@ int main() auto payload = pushArgs.Payload(); std::wstring payloadString(payload.begin(), payload.end()); - output = !payloadString.compare(c_rawNotificationPayload); + failed = !payloadString.compare(c_rawNotificationPayload); } - return 0; + return !failed; }; diff --git a/test/inc/TestDef.h b/test/inc/TestDef.h index aadee21f36..96fb1a0879 100644 --- a/test/inc/TestDef.h +++ b/test/inc/TestDef.h @@ -17,9 +17,9 @@ static const std::wstring c_testFilePhaseEventName = L"ReunionTestFilePhaseEvent static const std::wstring c_testStartupPhaseEventName = L"ReunionTestStartupPhaseEventName"; static const std::wstring c_testInstanceRedirectedPhaseEventName = L"ReunionTestInstanceRedirectedPhaseEventName"; -static const winrt::hstring c_rawNotificationPayload = L""; -static const IID c_comServerId = winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2"); -static const IID c_fakeComServerId = winrt::guid("00000000-0000-0000-0000-000000000001"); +inline const winrt::hstring c_rawNotificationPayload = L""; +inline IID c_comServerId = winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2"); +inline IID c_fakeComServerId = winrt::guid("00000000-0000-0000-0000-000000000001"); #ifndef WIDEN2 #define WIDEN2(x) L ## x From b17b91a5e152358fe85f2a7dcd93712772774a7d Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Tue, 1 Jun 2021 16:09:04 -0700 Subject: [PATCH 27/53] Add package install with version / arch --- .../PushNotificationChannel.cpp | 20 +++-- test/PushNotificationTests/APITests.cpp | 76 ++++++++----------- .../MockRawNotification.cpp | 6 +- test/PushNotificationTests/pch.h | 2 + .../PushNotificationsDemoApp/main.cpp | 2 +- .../PushNotificationsTestApp/main.cpp | 14 ++-- test/inc/ProjectReunion.Test.Package.h | 55 ++++++++++++-- test/inc/TestDef.h | 4 +- 8 files changed, 106 insertions(+), 73 deletions(-) diff --git a/dev/PushNotifications/PushNotificationChannel.cpp b/dev/PushNotifications/PushNotificationChannel.cpp index a1f0211d0c..00dba63be8 100644 --- a/dev/PushNotifications/PushNotificationChannel.cpp +++ b/dev/PushNotifications/PushNotificationChannel.cpp @@ -7,21 +7,25 @@ #include #include -namespace winrt +namespace winrt::Windows { - using namespace Windows::Networking::PushNotifications; - using namespace Windows::Foundation; + using namespace winrt::Windows::Networking::PushNotifications; + using namespace winrt::Windows::Foundation; +} +namespace winrt::Microsoft +{ + using namespace winrt::Microsoft::Windows::PushNotifications; } namespace winrt::Microsoft::Windows::PushNotifications::implementation { - PushNotificationChannel::PushNotificationChannel(winrt::PushNotificationChannel const& channel): m_channel(channel) {} + PushNotificationChannel::PushNotificationChannel(winrt::Windows::PushNotificationChannel const& channel): m_channel(channel) {} - winrt::Uri PushNotificationChannel::Uri() + winrt::Windows::Uri PushNotificationChannel::Uri() { - return winrt::Uri{ m_channel.Uri() }; + return winrt::Windows::Uri{ m_channel.Uri() }; } - winrt::DateTime PushNotificationChannel::ExpirationTime() + winrt::Windows::DateTime PushNotificationChannel::ExpirationTime() { return m_channel.ExpirationTime(); } @@ -30,7 +34,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation m_channel.Close(); } - winrt::event_token PushNotificationChannel::PushReceived(winrt::TypedEventHandler const& handler) + winrt::event_token PushNotificationChannel::PushReceived(winrt::Windows::TypedEventHandler const& handler) { return m_channel.PushNotificationReceived([weak_self = get_weak(), handler](auto&&, auto&& args) { diff --git a/test/PushNotificationTests/APITests.cpp b/test/PushNotificationTests/APITests.cpp index 7b90a432c7..81689d1d24 100644 --- a/test/PushNotificationTests/APITests.cpp +++ b/test/PushNotificationTests/APITests.cpp @@ -24,13 +24,9 @@ namespace Test::PushNotifications { private: wil::unique_event m_failed; - HANDLE m_process; + wil::unique_handle m_processHandle; winrt::com_ptr m_testAppLauncher; - //const std::wstring c_testPackageFile = g_deploymentDir + L"PushNotificationsTestAppPackage.msix"; - //const std::wstring c_testPackageFullName = L"PushNotificationsTestAppPackage_1.0.0.0_" PROJECTREUNION_TEST_PACKAGE_DDLM_ARCHITECTURE L"__8wekyb3d8bbwe"; - //const std::wstring c_testVCLibsPackageFile = g_deploymentDir + L"VCLibs.appx"; - public: BEGIN_TEST_CLASS(APITests) TEST_CLASS_PROPERTY(L"Description", L"Project Reunion Push Notifications test") @@ -38,28 +34,21 @@ namespace Test::PushNotifications TEST_CLASS_PROPERTY(L"RunAs:Class", L"RestrictedUser") END_TEST_CLASS() - static std::wstring GetDeploymentDir() + static PCWSTR GetDeploymentDir() { WEX::Common::String testDeploymentDir; WEX::TestExecution::RuntimeParameters::TryGetValue(L"TestDeploymentDir", testDeploymentDir); return reinterpret_cast(testDeploymentDir.GetBuffer()); } - static std::filesystem::path GetTestVCLibsPackageFile() - { - auto filename{ std::filesystem::path(GetDeploymentDir()) }; - filename /= L"VCLibs.appx"; - return filename; - } - static std::filesystem::path GetTestPackageFile() { auto filename{ std::filesystem::path(GetDeploymentDir()) }; - filename /= L"PushNotificationsTestAppPackage.msix"; + filename /= L"PushNotificationsTestAppPackage"; return filename; } - static std::wstring GetTestPackageFullName() + static PCWSTR GetTestPackageFullName() { return L"PushNotificationsTestAppPackage_1.0.0.0_" PROJECTREUNION_TEST_PACKAGE_DDLM_ARCHITECTURE L"__8wekyb3d8bbwe"; } @@ -68,9 +57,8 @@ namespace Test::PushNotifications { try { - TP::AddPackage_ProjectReunionFramework(); - InstallPackage(GetTestVCLibsPackageFile()); - InstallPackage(GetTestPackageFile()); + TP::AddPackage_ProjectReunionFramework(); // Installs PRfwk + TW::AddPackage(L"PushNotificationsTestAppPackage", L"1.0.0.0"); // Installs PushNotificationsTestApp.msix } catch (...) { @@ -78,7 +66,6 @@ namespace Test::PushNotifications } m_testAppLauncher = winrt::create_instance(CLSID_ApplicationActivationManager, CLSCTX_ALL); - VERIFY_IS_NOT_NULL(m_testAppLauncher); return true; } @@ -87,7 +74,7 @@ namespace Test::PushNotifications try { TP::RemovePackage_ProjectReunionFramework(); - UninstallPackage(GetTestPackageFullName()); + TP::RemovePackage(GetTestPackageFullName()); } catch (...) { @@ -106,35 +93,31 @@ namespace Test::PushNotifications { VERIFY_IS_TRUE(TP::IsPackageRegistered_ProjectReunionFramework()); - if (m_process) + if (m_processHandle) { - VERIFY_IS_TRUE(CloseHandle(m_process)); + m_processHandle.reset(); } return true; } - void RunTest(const PCWSTR& testName) + void RunTest(const PCWSTR& testName, const int& waitTime) { - DWORD pid; - VERIFY_SUCCEEDED(m_testAppLauncher.get()->ActivateApplication(L"PushNotificationsTestAppPackage_8wekyb3d8bbwe!App", testName, AO_NONE, &pid)); - VERIFY_IS_NOT_NULL(pid); + DWORD processId; + VERIFY_SUCCEEDED(m_testAppLauncher.get()->ActivateApplication(L"PushNotificationsTestAppPackage_8wekyb3d8bbwe!App", testName, AO_NONE, &processId)); - m_process = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid); - VERIFY_IS_NOT_NULL(m_process); + m_processHandle = wil::unique_handle(OpenProcess(SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processId)); + VERIFY_IS_TRUE(m_processHandle.is_valid()); - VERIFY_ARE_EQUAL(WaitForSingleObject(m_process, 3000), WAIT_OBJECT_0); + VERIFY_ARE_EQUAL(WaitForSingleObject(m_processHandle.get(), waitTime), WAIT_OBJECT_0); DWORD exitCode; - VERIFY_IS_TRUE(GetExitCodeProcess(m_process, &exitCode)); + VERIFY_WIN32_BOOL_SUCCEEDED(GetExitCodeProcess(m_processHandle.get(), &exitCode)); VERIFY_ARE_EQUAL(exitCode, 0); - - VERIFY_IS_TRUE(CloseHandle(m_process)); - m_process = nullptr; } TEST_METHOD(BackgroundActivation) { - RunTest(nullptr); // Just need to launch. + RunTest(nullptr, c_pushTestWait); // Need to launch one time to enable background activation. auto LocalBackgroundTask = winrt::create_instance(c_comServerId, CLSCTX_ALL); auto mockBackgroundTaskInstance = winrt::make(); @@ -143,52 +126,53 @@ namespace Test::PushNotifications TEST_METHOD(ChannelRequestUsingNullRemoteId) { - RunTest(L"ChannelRequestUsingNullRemoteId"); + RunTest(L"ChannelRequestUsingNullRemoteId", c_pushTestWait); } TEST_METHOD(ChannelRequestUsingRemoteId) { - RunTest(L"ChannelRequestUsingRemoteId"); + RunTest(L"ChannelRequestUsingRemoteId", c_pushTestChannelWait); } - /*TEST_METHOD(MultipleChannelRequestUsingSameRemoteId) + TEST_METHOD(MultipleChannelRequestUsingSameRemoteId) { - RunTest(L"MultipleChannelRequestUsingSameRemoteId"); + RunTest(L"MultipleChannelRequestUsingSameRemoteId", c_pushTestChannelWait); } TEST_METHOD(MultipleChannelRequestUsingMultipleRemoteId) { - RunTest(L"MultipleChannelRequestUsingMultipleRemoteId"); - }*/ + RunTest(L"MultipleChannelRequestUsingMultipleRemoteId", c_pushTestChannelWait); + } TEST_METHOD(ActivatorTest) { - RunTest(L"ActivatorTest"); + RunTest(L"ActivatorTest", c_pushTestWait); } TEST_METHOD(RegisterActivatorNullDetails) { - RunTest(L"RegisterActivatorNullDetails"); + RunTest(L"RegisterActivatorNullDetails", c_pushTestWait); } TEST_METHOD(RegisterActivatorNullClsid) { - RunTest(L"RegisterActivatorNullClsid"); + RunTest(L"RegisterActivatorNullClsid", c_pushTestWait); } TEST_METHOD(UnregisterActivatorNullToken) { - RunTest(L"UnregisterActivatorNullToken"); + RunTest(L"UnregisterActivatorNullToken", c_pushTestWait); } TEST_METHOD(UnregisterActivatorNullBackgroundRegistration) { - RunTest(L"UnregisterActivatorNullBackgroundRegistration"); + RunTest(L"UnregisterActivatorNullBackgroundRegistration", c_pushTestWait); } TEST_METHOD(MultipleRegisterActivatorTest) { - RunTest(L"MultipleRegisterActivatorTest"); + RunTest(L"MultipleRegisterActivatorTest", c_pushTestWait); } + }; } diff --git a/test/PushNotificationTests/MockRawNotification.cpp b/test/PushNotificationTests/MockRawNotification.cpp index 465c115279..e6dfe21413 100644 --- a/test/PushNotificationTests/MockRawNotification.cpp +++ b/test/PushNotificationTests/MockRawNotification.cpp @@ -18,7 +18,7 @@ winrt::hstring MockRawNotification::Content() winrt::Windows::Storage::Streams::IBuffer MockRawNotification::ContentBytes() { - winrt::Windows::Storage::Streams::DataWriter dataWriter{}; - dataWriter.WriteString(c_rawNotificationPayload); - return dataWriter.DetachBuffer(); + return winrt::Windows::Security::Cryptography::CryptographicBuffer::ConvertStringToBinary( + c_rawNotificationPayload, + winrt::Windows::Security::Cryptography::BinaryStringEncoding::Utf8); } diff --git a/test/PushNotificationTests/pch.h b/test/PushNotificationTests/pch.h index 60112bed3f..2a7aa6bcc7 100644 --- a/test/PushNotificationTests/pch.h +++ b/test/PushNotificationTests/pch.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -36,3 +37,4 @@ #include namespace TP = ::Test::Packages; +namespace TW = ::Test::WapProj; diff --git a/test/TestApps/PushNotificationsDemoApp/main.cpp b/test/TestApps/PushNotificationsDemoApp/main.cpp index 654a9bf063..65b19588c3 100644 --- a/test/TestApps/PushNotificationsDemoApp/main.cpp +++ b/test/TestApps/PushNotificationsDemoApp/main.cpp @@ -84,7 +84,7 @@ winrt::Windows::Foundation::IAsyncOperation RequestChan winrt::Microsoft::Windows::PushNotifications::PushNotificationChannel RequestChannel() { auto task = RequestChannelAsync(); - if (task.wait_for(std::chrono::seconds(960)) != AsyncStatus::Completed) + if (task.wait_for(std::chrono::seconds(300)) != AsyncStatus::Completed) { task.Cancel(); return nullptr; diff --git a/test/TestApps/PushNotificationsTestApp/main.cpp b/test/TestApps/PushNotificationsTestApp/main.cpp index cd3bd56944..dd90f76dc7 100644 --- a/test/TestApps/PushNotificationsTestApp/main.cpp +++ b/test/TestApps/PushNotificationsTestApp/main.cpp @@ -68,7 +68,7 @@ bool ChannelRequestUsingNullRemoteId() HRESULT ChannelRequestHelper(IAsyncOperationWithProgress const& channelOperation) { - if (channelOperation.wait_for(std::chrono::seconds(960)) != AsyncStatus::Completed) + if (channelOperation.wait_for(std::chrono::seconds(300)) != AsyncStatus::Completed) { channelOperation.Cancel(); return ERROR_TIMEOUT; // timed out or failed @@ -101,7 +101,7 @@ bool MultipleChannelRequestUsingSameRemoteId() auto channelOperationResult2 = ChannelRequestHelper(channelOperation2); auto channelOperationResult1 = ChannelRequestHelper(channelOperation1); - return channelOperationResult2 == WPN_E_OUTSTANDING_CHANNEL_REQUEST; + return channelOperationResult2 == S_OK; } bool MultipleChannelRequestUsingMultipleRemoteId() @@ -111,7 +111,7 @@ bool MultipleChannelRequestUsingMultipleRemoteId() auto channelOperationResult2 = ChannelRequestHelper(channelOperation2); auto channelOperationResult1 = ChannelRequestHelper(channelOperation1); - return channelOperationResult2 == WPN_E_OUTSTANDING_CHANNEL_REQUEST; + return channelOperationResult2 == S_OK; } bool ActivatorTest() @@ -280,7 +280,7 @@ void UnregisterClsid() int main() { initUnitTestMapping(); - bool failed = false; + bool testResult = false; auto scope_exit = wil::scope_exit([&] { UnregisterClsid(); }); @@ -300,7 +300,7 @@ int main() std::string unitTest = to_string(launchArgs.Arguments()); std::cout << unitTest << std::endl; - failed = runUnitTest(unitTest); + testResult = runUnitTest(unitTest); } else if (kind == ExtendedActivationKind::Push) { @@ -308,8 +308,8 @@ int main() auto payload = pushArgs.Payload(); std::wstring payloadString(payload.begin(), payload.end()); - failed = !payloadString.compare(c_rawNotificationPayload); + testResult = !payloadString.compare(c_rawNotificationPayload); } - return !failed; + return testResult ? 0 : 1; // We want 0 to be success and 1 failure }; diff --git a/test/inc/ProjectReunion.Test.Package.h b/test/inc/ProjectReunion.Test.Package.h index 12789124c6..210bfe4d7c 100644 --- a/test/inc/ProjectReunion.Test.Package.h +++ b/test/inc/ProjectReunion.Test.Package.h @@ -131,14 +131,14 @@ namespace Test::Packages msix /= packageDirName; msix /= packageDirName; msix += L".msix"; -WIN32_FILE_ATTRIBUTE_DATA data{}; -const auto ok{ GetFileAttributesExW(msix.c_str(), GetFileExInfoStandard, &data) }; -const auto lastError{ ::GetLastError() }; -WEX::Logging::Log::Comment(WEX::Common::String().Format(L"GetFileAttributesExW(%ls):%d LastError:%u", msix.c_str(), static_cast(ok), lastError)); + WIN32_FILE_ATTRIBUTE_DATA data{}; + const auto ok{ GetFileAttributesExW(msix.c_str(), GetFileExInfoStandard, &data) }; + const auto lastError{ ::GetLastError() }; + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"GetFileAttributesExW(%ls):%d LastError:%u", msix.c_str(), static_cast(ok), lastError)); -std::error_code errorcode{}; -auto isregularfile{ std::filesystem::is_regular_file(msix, errorcode) }; -WEX::Logging::Log::Comment(WEX::Common::String().Format(L"std::filesystem::is_regular_file(%ls):%ls error_code:%d %hs", msix.c_str(), isregularfile ? L"True" : L"False", errorcode.value(), errorcode.message().c_str())); + std::error_code errorcode{}; + auto isregularfile{ std::filesystem::is_regular_file(msix, errorcode) }; + WEX::Logging::Log::Comment(WEX::Common::String().Format(L"std::filesystem::is_regular_file(%ls):%ls error_code:%d %hs", msix.c_str(), isregularfile ? L"True" : L"False", errorcode.value(), errorcode.message().c_str())); //VERIFY_IS_TRUE(std::filesystem::is_regular_file(msix)); } @@ -250,4 +250,45 @@ WEX::Logging::Log::Comment(WEX::Common::String().Format(L"std::filesystem::is_re } } +constexpr PCWSTR GetCurrentArchitectureAsString() +{ +#if defined(_M_X64) + return L"x64"; +#elif defined(_M_IX86) + return L"x86"; +#elif defined(_M_ARM64) + return L"arm64"; +#elif defined(_M_ARM) + return L"arm"; +#else +# error "Unknown processor architecture" +#endif +} + +namespace Test::WapProj +{ + inline void AddPackage(PCWSTR packageDirName, PCWSTR packageName, PCWSTR packageVersion) + { + auto msix(::Test::FileSystem::GetSolutionOutDirPath()); + msix /= packageDirName; + msix /= packageName; + msix += "_"; + msix += packageVersion; + msix += "_"; + msix += GetCurrentArchitectureAsString(); + msix += ".msix"; + auto msixUri = winrt::Windows::Foundation::Uri(msix.c_str()); + + // Install the package + winrt::Windows::Management::Deployment::PackageManager packageManager; + auto options{ winrt::Windows::Management::Deployment::DeploymentOptions::None }; + auto deploymentResult{ packageManager.AddPackageAsync(msixUri, nullptr, options).get() }; + VERIFY_SUCCEEDED(deploymentResult.ExtendedErrorCode(), WEX::Common::String().Format(L"AddPackageAsync('%s') = 0x%0X %s", msix.c_str(), deploymentResult.ExtendedErrorCode(), deploymentResult.ErrorText().c_str())); + } + + inline void AddPackage(PCWSTR packageDirName, PCWSTR packageVersion) + { + AddPackage(packageDirName, packageDirName, packageVersion); + } +} #endif // __PROJECTREUNION_TEST_PACKAGE_H diff --git a/test/inc/TestDef.h b/test/inc/TestDef.h index 96fb1a0879..e0e9dd1548 100644 --- a/test/inc/TestDef.h +++ b/test/inc/TestDef.h @@ -15,11 +15,13 @@ static const std::wstring c_testFileExtension_Packaged = L".reuniontestfile-pack static const std::wstring c_testFilePhaseEventName = L"ReunionTestFilePhaseEventName"; static const std::wstring c_testStartupPhaseEventName = L"ReunionTestStartupPhaseEventName"; - static const std::wstring c_testInstanceRedirectedPhaseEventName = L"ReunionTestInstanceRedirectedPhaseEventName"; + inline const winrt::hstring c_rawNotificationPayload = L""; inline IID c_comServerId = winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2"); inline IID c_fakeComServerId = winrt::guid("00000000-0000-0000-0000-000000000001"); +inline const int c_pushTestWait = 3000; +inline const int c_pushTestChannelWait = 303000; #ifndef WIDEN2 #define WIDEN2(x) L ## x From 34c14e684baef34db533a856b98a0e9718f59fbc Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Tue, 1 Jun 2021 16:14:18 -0700 Subject: [PATCH 28/53] Added multiple background activation test --- test/PushNotificationTests/APITests.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/PushNotificationTests/APITests.cpp b/test/PushNotificationTests/APITests.cpp index 81689d1d24..81cde50778 100644 --- a/test/PushNotificationTests/APITests.cpp +++ b/test/PushNotificationTests/APITests.cpp @@ -124,6 +124,21 @@ namespace Test::PushNotifications VERIFY_NO_THROW(LocalBackgroundTask.Run(mockBackgroundTaskInstance)); } + TEST_METHOD(MultipleBackgroundActivation) + { + RunTest(nullptr, c_pushTestWait); // Need to launch one time to enable background activation. + + auto LocalBackgroundTask1 = winrt::create_instance(c_comServerId, CLSCTX_ALL); + auto mockBackgroundTaskInstance1 = winrt::make(); + + auto LocalBackgroundTask2 = winrt::create_instance(c_comServerId, CLSCTX_ALL); + auto mockBackgroundTaskInstance2 = winrt::make(); + + VERIFY_NO_THROW(LocalBackgroundTask1.Run(mockBackgroundTaskInstance1)); + VERIFY_NO_THROW(LocalBackgroundTask2.Run(mockBackgroundTaskInstance2)); + + } + TEST_METHOD(ChannelRequestUsingNullRemoteId) { RunTest(L"ChannelRequestUsingNullRemoteId", c_pushTestWait); From 9683ab87e799938dc1304ff649131aa5487f31df Mon Sep 17 00:00:00 2001 From: Scott Darnell <20483794+aeloros@users.noreply.github.com> Date: Wed, 2 Jun 2021 12:35:51 -0700 Subject: [PATCH 29/53] PR feedback Co-authored-by: Raymond Chen --- dev/AppLifecycle/AppInstance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/AppLifecycle/AppInstance.cpp b/dev/AppLifecycle/AppInstance.cpp index f84ddef151..b95266ea4b 100644 --- a/dev/AppLifecycle/AppInstance.cpp +++ b/dev/AppLifecycle/AppInstance.cpp @@ -348,7 +348,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation if (contractData.empty()) { // If the contractData is empty, handle any aliased encoded launches. - if (CompareStringOrdinal(contractArgument.c_str(), -1, L"ReunionPushServer", -1, TRUE) == CSTR_EQUAL) + if (CompareStringOrdinal(contractArgument.data(), contractArgument.size(), L"ReunionPushServer", -1, TRUE) == CSTR_EQUAL) { contractData = GenerateEncodedLaunchUri(L"App", c_pushContractId); contractArgument = c_protocolArgumentString; From 162ef687fa95551ea77ab34a36be917ae6d500b8 Mon Sep 17 00:00:00 2001 From: Scott Darnell <20483794+aeloros@users.noreply.github.com> Date: Wed, 2 Jun 2021 12:36:21 -0700 Subject: [PATCH 30/53] PR Feedback Co-authored-by: Raymond Chen --- dev/AppLifecycle/AppInstance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/AppLifecycle/AppInstance.cpp b/dev/AppLifecycle/AppInstance.cpp index b95266ea4b..65fe405a3f 100644 --- a/dev/AppLifecycle/AppInstance.cpp +++ b/dev/AppLifecycle/AppInstance.cpp @@ -359,7 +359,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation { kind = ExtendedActivationKind::Protocol; auto args = make(contractData); - data = args.as(); + data = args; // Encoded launch is a protocol launch where the argument data is // encapsulated in the Uri Query data. We handle that here and From f05c96a77154a5bdabfcdc1104a2e6338631a4b2 Mon Sep 17 00:00:00 2001 From: Scott Darnell <20483794+aeloros@users.noreply.github.com> Date: Wed, 2 Jun 2021 12:37:46 -0700 Subject: [PATCH 31/53] PR Feedback Co-authored-by: Raymond Chen --- dev/AppLifecycle/AppInstance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/AppLifecycle/AppInstance.cpp b/dev/AppLifecycle/AppInstance.cpp index 65fe405a3f..e87b4b9d16 100644 --- a/dev/AppLifecycle/AppInstance.cpp +++ b/dev/AppLifecycle/AppInstance.cpp @@ -381,7 +381,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation if (!foundArgs) { kind = ExtendedActivationKind::Launch; - data = make(commandLine).as(); + data = make(commandLine); } return make(kind, data); From 9c3d97788428501cf0be63f25c89c9d5d50ff4ae Mon Sep 17 00:00:00 2001 From: Scott Darnell <20483794+aeloros@users.noreply.github.com> Date: Wed, 2 Jun 2021 16:29:24 -0700 Subject: [PATCH 32/53] PR Feedback --- dev/AppLifecycle/AppInstance.cpp | 17 +++++------------ dev/AppLifecycle/ExtensionContract.h | 11 ++++++----- dev/AppLifecycle/FileActivatedEventArgs.h | 12 ++++++------ dev/AppLifecycle/LaunchActivatedEventArgs.h | 10 +++++----- dev/AppLifecycle/ProtocolActivatedEventArgs.h | 8 ++++---- dev/AppLifecycle/StartupActivatedEventArgs.h | 8 ++++---- .../GetRawNotificationEventArgs.h | 2 +- 7 files changed, 31 insertions(+), 37 deletions(-) diff --git a/dev/AppLifecycle/AppInstance.cpp b/dev/AppLifecycle/AppInstance.cpp index e87b4b9d16..b2b921339d 100644 --- a/dev/AppLifecycle/AppInstance.cpp +++ b/dev/AppLifecycle/AppInstance.cpp @@ -64,10 +64,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation std::tuple GetEncodedLaunchActivatedEventArgs(IProtocolActivatedEventArgs const& args) { - auto kind = ExtendedActivationKind::Protocol; - winrt::Windows::Foundation::IInspectable data; - - std::tie(kind, data) = DecodeActivatedEventArgs(args.Uri()); + auto [kind, data] = DecodeActivatedEventArgs(args.Uri()); // Let the caller args pass through if nothing was determined here. if (data == nullptr) @@ -336,10 +333,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation std::wstring commandLine = std::wstring(GetCommandLine()); if (!foundArgs) { - std::wstring contractArgument; - std::wstring contractData; - - std::tie(contractArgument, contractData) = ParseCommandLine(commandLine); + auto [contractArgument, contractData] = ParseCommandLine(commandLine); // All specific launch types are encoded as a URI and transported as a // protocol, except the catch-all LaunchActivatedEventArgs case. @@ -348,7 +342,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation if (contractData.empty()) { // If the contractData is empty, handle any aliased encoded launches. - if (CompareStringOrdinal(contractArgument.data(), contractArgument.size(), L"ReunionPushServer", -1, TRUE) == CSTR_EQUAL) + if (CompareStringOrdinal(contractArgument.data(), static_cast(contractArgument.size()), L"ReunionPushServer", -1, TRUE) == CSTR_EQUAL) { contractData = GenerateEncodedLaunchUri(L"App", c_pushContractId); contractArgument = c_protocolArgumentString; @@ -366,10 +360,9 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation // try to return the correct IActivatedEventArgs type that is // encoded in the data rather than the IProtocolActivatedEventArgs // itself. - auto protocolArgs = args.as(); - if (IsEncodedLaunch(protocolArgs.Uri())) + if (IsEncodedLaunch(args.Uri())) { - std::tie(kind, data) = GetEncodedLaunchActivatedEventArgs(protocolArgs); + std::tie(kind, data) = GetEncodedLaunchActivatedEventArgs(args); } foundArgs = true; diff --git a/dev/AppLifecycle/ExtensionContract.h b/dev/AppLifecycle/ExtensionContract.h index 54b9f87974..ac532a5a68 100644 --- a/dev/AppLifecycle/ExtensionContract.h +++ b/dev/AppLifecycle/ExtensionContract.h @@ -12,13 +12,14 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation { // This array holds the mapping between a class factory and it's extension contract Id. - static const struct ExtensionMap + struct ExtensionMap { ExtendedActivationKind kind; - std::wstring contractId; + PCWSTR contractId; winrt::Windows::Foundation::IInspectable(*factory)(winrt::Windows::Foundation::Uri const& uri); - } - c_extensionMap[] = + }; + + constexpr ExtensionMap c_extensionMap[] = { { ExtendedActivationKind::Launch, c_launchContractId, &LaunchActivatedEventArgs::Deserialize }, { ExtendedActivationKind::File, c_fileContractId, &FileActivatedEventArgs::Deserialize }, @@ -41,7 +42,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation for (const auto& extension : c_extensionMap) { std::wstring contractId = pair.Value().c_str(); - if (CompareStringOrdinal(contractId.c_str(), -1, extension.contractId.c_str(), -1, TRUE) == CSTR_EQUAL) + if (CompareStringOrdinal(contractId.c_str(), -1, extension.contractId, -1, TRUE) == CSTR_EQUAL) { return { extension.kind, extension.factory(uri).as() }; } diff --git a/dev/AppLifecycle/FileActivatedEventArgs.h b/dev/AppLifecycle/FileActivatedEventArgs.h index d59b423187..9b217dc3fe 100644 --- a/dev/AppLifecycle/FileActivatedEventArgs.h +++ b/dev/AppLifecycle/FileActivatedEventArgs.h @@ -10,9 +10,9 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation using namespace winrt::Windows::ApplicationModel::Activation; using namespace winrt::Windows::Storage; - static PCWSTR c_fileContractId = L"Windows.File"; + constexpr PCWSTR c_fileContractId = L"Windows.File"; - class FileActivatedEventArgs : public winrt::implements { public: @@ -29,8 +29,8 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation } m_kind = ActivationKind::File; - m_verb = verb; - m_path = file; + m_verb = std::move(verb); + m_path = std::move(file); m_files = winrt::single_threaded_vector(); // There is a scenario where we just want to create an object to serialize it. In that situation @@ -47,8 +47,8 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation static winrt::Windows::Foundation::IInspectable Deserialize(winrt::Windows::Foundation::Uri const& uri) { auto query = uri.QueryParsed(); - std::wstring verb = query.GetFirstValueByName(L"Verb").c_str(); - std::wstring file = query.GetFirstValueByName(L"File").c_str(); + auto verb = std::wstring(query.GetFirstValueByName(L"Verb")); + auto file = std::wstring(query.GetFirstValueByName(L"File")); return make(verb, file); } diff --git a/dev/AppLifecycle/LaunchActivatedEventArgs.h b/dev/AppLifecycle/LaunchActivatedEventArgs.h index ccf2bbd128..0588b0c255 100644 --- a/dev/AppLifecycle/LaunchActivatedEventArgs.h +++ b/dev/AppLifecycle/LaunchActivatedEventArgs.h @@ -9,13 +9,13 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation { using namespace winrt::Windows::ApplicationModel::Activation; - static PCWSTR c_launchContractId = L"Windows.Launch"; + constexpr PCWSTR c_launchContractId = L"Windows.Launch"; - class LaunchActivatedEventArgs : public winrt::implements + class LaunchActivatedEventArgs : public winrt::implements { public: - LaunchActivatedEventArgs(const std::wstring& args) : m_args(args) + LaunchActivatedEventArgs(const std::wstring& args) : m_args(std::move(args)) { m_kind = ActivationKind::Launch; } @@ -23,7 +23,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation static winrt::Windows::Foundation::IInspectable Deserialize(winrt::Windows::Foundation::Uri const& uri) { auto query = uri.QueryParsed(); - auto args = query.GetFirstValueByName(L"Arguments").c_str(); + auto args = std::wstring(query.GetFirstValueByName(L"Arguments")); return make(args); } diff --git a/dev/AppLifecycle/ProtocolActivatedEventArgs.h b/dev/AppLifecycle/ProtocolActivatedEventArgs.h index e64beb9094..988ba900dd 100644 --- a/dev/AppLifecycle/ProtocolActivatedEventArgs.h +++ b/dev/AppLifecycle/ProtocolActivatedEventArgs.h @@ -10,13 +10,13 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation using namespace winrt::Windows::Foundation::Collections; using namespace winrt::Windows::ApplicationModel::Activation; - static PCWSTR c_protocolContractId = L"Windows.Protocol"; + constexpr PCWSTR c_protocolContractId = L"Windows.Protocol"; - class ProtocolActivatedEventArgs : public winrt::implements { public: - ProtocolActivatedEventArgs(const std::wstring& uri) : m_uri(winrt::Windows::Foundation::Uri(uri)) + ProtocolActivatedEventArgs(const std::wstring& uri) : m_uri(winrt::Windows::Foundation::Uri(std::move(uri))) { m_kind = ActivationKind::Protocol; } @@ -24,7 +24,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation static winrt::Windows::Foundation::IInspectable Deserialize(winrt::Windows::Foundation::Uri const& uri) { auto query = uri.QueryParsed(); - auto args = query.GetFirstValueByName(L"Uri").c_str(); + auto args = std::wstring(query.GetFirstValueByName(L"Uri")); return make(args); } diff --git a/dev/AppLifecycle/StartupActivatedEventArgs.h b/dev/AppLifecycle/StartupActivatedEventArgs.h index 4fb39bc79e..56bb6961b2 100644 --- a/dev/AppLifecycle/StartupActivatedEventArgs.h +++ b/dev/AppLifecycle/StartupActivatedEventArgs.h @@ -9,10 +9,10 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation { using namespace winrt::Windows::ApplicationModel::Activation; - static PCWSTR c_startupTaskContractId = L"Windows.StartupTask"; + constexpr PCWSTR c_startupTaskContractId = L"Windows.StartupTask"; - class StartupActivatedEventArgs : public winrt::implements + class StartupActivatedEventArgs : public winrt::implements { public: StartupActivatedEventArgs(const std::wstring& taskId) : m_taskId(taskId) @@ -23,7 +23,7 @@ namespace winrt::Microsoft::Windows::AppLifecycle::implementation static winrt::Windows::Foundation::IInspectable Deserialize(winrt::Windows::Foundation::Uri const& uri) { auto query = uri.QueryParsed(); - std::wstring taskId = query.GetFirstValueByName(L"TaskId").c_str(); + auto taskId = std::wstring(query.GetFirstValueByName(L"TaskId")); return make(taskId); } diff --git a/dev/PushNotifications/GetRawNotificationEventArgs.h b/dev/PushNotifications/GetRawNotificationEventArgs.h index 2d790dc016..1f1b6c8937 100644 --- a/dev/PushNotifications/GetRawNotificationEventArgs.h +++ b/dev/PushNotifications/GetRawNotificationEventArgs.h @@ -6,7 +6,7 @@ #include #include "externs.h" -static PCWSTR c_pushContractId = L"Windows.Push"; +constexpr PCWSTR c_pushContractId = L"Windows.Push"; using namespace winrt::Windows::ApplicationModel::Core; namespace winrt::Microsoft::Windows::PushNotifications From 478b45524ddf6dcc79d2f9b92d757a3cab4c2ba8 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Wed, 2 Jun 2021 15:44:49 -0700 Subject: [PATCH 33/53] Address PR comments --- .../PushNotificationBackgroundTask.h | 12 +++++++++++- .../PushNotificationChannel.cpp | 18 ++++++++++++++++-- test/PushNotificationTests/APITests.cpp | 4 ++-- test/PushNotificationTests/pch.h | 1 - test/inc/ProjectReunion.Test.Package.h | 2 +- test/inc/TestDef.h | 2 +- 6 files changed, 31 insertions(+), 8 deletions(-) diff --git a/dev/PushNotifications/PushNotificationBackgroundTask.h b/dev/PushNotifications/PushNotificationBackgroundTask.h index 9f763af7cb..f5c95e7f0d 100644 --- a/dev/PushNotifications/PushNotificationBackgroundTask.h +++ b/dev/PushNotifications/PushNotificationBackgroundTask.h @@ -3,6 +3,8 @@ #include +static long g_backgroundTaskServerLock = 0; + struct PushNotificationBackgroundTask : winrt::implements { PushNotificationBackgroundTask() {} @@ -24,8 +26,16 @@ struct PushNotificationBackgroundTaskFactory : winrt::implements().as(interfaceId, object); } - HRESULT __stdcall LockServer(BOOL) noexcept final + HRESULT __stdcall LockServer(BOOL lock) noexcept final { + if (lock) + { + InterlockedIncrement(&g_backgroundTaskServerLock); + } + else + { + InterlockedDecrement(&g_backgroundTaskServerLock); + } return S_OK; } }; diff --git a/dev/PushNotifications/PushNotificationChannel.cpp b/dev/PushNotifications/PushNotificationChannel.cpp index 00dba63be8..11ef2ddee1 100644 --- a/dev/PushNotifications/PushNotificationChannel.cpp +++ b/dev/PushNotifications/PushNotificationChannel.cpp @@ -31,7 +31,18 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } void PushNotificationChannel::Close() { - m_channel.Close(); + try + { + m_channel.Close(); + } + catch (...) + { + auto channelCloseException = hresult_error(to_hresult()); + if (channelCloseException.code() != HRESULT_FROM_WIN32(ERROR_NOT_FOUND)) + { + throw channelCloseException; + } + } } winrt::event_token PushNotificationChannel::PushReceived(winrt::Windows::TypedEventHandler const& handler) @@ -39,7 +50,10 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation return m_channel.PushNotificationReceived([weak_self = get_weak(), handler](auto&&, auto&& args) { auto strong = weak_self.get(); - if (strong) handler(*strong, PushNotificationReceivedEventArgs::CreateFromPushNotificationReceivedEventArgs(args)); + if (strong) + { + handler(*strong, PushNotificationReceivedEventArgs::CreateFromPushNotificationReceivedEventArgs(args)); + }; }); } diff --git a/test/PushNotificationTests/APITests.cpp b/test/PushNotificationTests/APITests.cpp index 81cde50778..687893616e 100644 --- a/test/PushNotificationTests/APITests.cpp +++ b/test/PushNotificationTests/APITests.cpp @@ -58,7 +58,7 @@ namespace Test::PushNotifications try { TP::AddPackage_ProjectReunionFramework(); // Installs PRfwk - TW::AddPackage(L"PushNotificationsTestAppPackage", L"1.0.0.0"); // Installs PushNotificationsTestApp.msix + TP::WapProj::AddPackage(L"PushNotificationsTestAppPackage", L"1.0.0.0"); // Installs PushNotificationsTestApp.msix } catch (...) { @@ -156,7 +156,7 @@ namespace Test::PushNotifications TEST_METHOD(MultipleChannelRequestUsingMultipleRemoteId) { - RunTest(L"MultipleChannelRequestUsingMultipleRemoteId", c_pushTestChannelWait); + RunTest(L"MultipleChannelRequestUsingMultipleRemoteId", c_pushTestChannelWait); } TEST_METHOD(ActivatorTest) diff --git a/test/PushNotificationTests/pch.h b/test/PushNotificationTests/pch.h index 2a7aa6bcc7..16cddcc86c 100644 --- a/test/PushNotificationTests/pch.h +++ b/test/PushNotificationTests/pch.h @@ -37,4 +37,3 @@ #include namespace TP = ::Test::Packages; -namespace TW = ::Test::WapProj; diff --git a/test/inc/ProjectReunion.Test.Package.h b/test/inc/ProjectReunion.Test.Package.h index 210bfe4d7c..8f91fc5a0a 100644 --- a/test/inc/ProjectReunion.Test.Package.h +++ b/test/inc/ProjectReunion.Test.Package.h @@ -265,7 +265,7 @@ constexpr PCWSTR GetCurrentArchitectureAsString() #endif } -namespace Test::WapProj +namespace Test::Packages::WapProj { inline void AddPackage(PCWSTR packageDirName, PCWSTR packageName, PCWSTR packageVersion) { diff --git a/test/inc/TestDef.h b/test/inc/TestDef.h index e0e9dd1548..65957bb20d 100644 --- a/test/inc/TestDef.h +++ b/test/inc/TestDef.h @@ -21,7 +21,7 @@ inline const winrt::hstring c_rawNotificationPayload = L""; inline IID c_comServerId = winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2"); inline IID c_fakeComServerId = winrt::guid("00000000-0000-0000-0000-000000000001"); inline const int c_pushTestWait = 3000; -inline const int c_pushTestChannelWait = 303000; +inline const int c_pushTestChannelWait = c_pushTestWait + 300000; // Need to wait 300000ms for channel request + 3000ms for application overhead #ifndef WIDEN2 #define WIDEN2(x) L ## x From 8a11f9cde29bb0428f6ea3e301bff7e3556a847b Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Thu, 3 Jun 2021 10:35:39 -0700 Subject: [PATCH 34/53] Fixed Debug unit tests --- test/PushNotificationTests/APITests.cpp | 3 +- .../PushNotificationTests.vcxproj | 3 -- .../PushNotificationTests.vcxproj.filters | 10 ++--- test/PushNotificationTests/Shared.cpp | 44 ------------------- test/PushNotificationTests/Shared.h | 9 ---- test/inc/ProjectReunion.Test.Package.h | 24 +++++----- 6 files changed, 15 insertions(+), 78 deletions(-) delete mode 100644 test/PushNotificationTests/Shared.cpp delete mode 100644 test/PushNotificationTests/Shared.h diff --git a/test/PushNotificationTests/APITests.cpp b/test/PushNotificationTests/APITests.cpp index 687893616e..1dd7b0536c 100644 --- a/test/PushNotificationTests/APITests.cpp +++ b/test/PushNotificationTests/APITests.cpp @@ -4,7 +4,6 @@ #include "pch.h" #include #include "MockBackgroundTaskInstance.h" -#include "Shared.h" using namespace WEX::Common; using namespace WEX::Logging; @@ -58,7 +57,7 @@ namespace Test::PushNotifications try { TP::AddPackage_ProjectReunionFramework(); // Installs PRfwk - TP::WapProj::AddPackage(L"PushNotificationsTestAppPackage", L"1.0.0.0"); // Installs PushNotificationsTestApp.msix + TP::WapProj::AddPackage(L"PushNotificationTests", L"PushNotificationsTestAppPackage", L".msix"); // Installs PushNotificationsTestApp.msix } catch (...) { diff --git a/test/PushNotificationTests/PushNotificationTests.vcxproj b/test/PushNotificationTests/PushNotificationTests.vcxproj index 6e365ea245..539787bfaf 100644 --- a/test/PushNotificationTests/PushNotificationTests.vcxproj +++ b/test/PushNotificationTests/PushNotificationTests.vcxproj @@ -156,7 +156,6 @@ - @@ -168,7 +167,6 @@ Create Create - @@ -176,7 +174,6 @@ .Debug _Debug - $(AppxPackageDir)\PushNotificationsTestAppPackage_1.0.0.0_$(PlatformTarget)$(TestPkgDebugConfigName)_Test $(OutDir)\PushNotificationsTestAppPackage\AppPackages\PushNotificationsTestAppPackage_1.0.0.0$(TestPkgDebugConfigName)_Test $(TestPkgOutputPath)\PushNotificationsTestAppPackage_1.0.0.0_$(PlatformTarget)$(TestPkgDebugConfigName).msix diff --git a/test/PushNotificationTests/PushNotificationTests.vcxproj.filters b/test/PushNotificationTests/PushNotificationTests.vcxproj.filters index e98f8d727d..658d31e6bb 100644 --- a/test/PushNotificationTests/PushNotificationTests.vcxproj.filters +++ b/test/PushNotificationTests/PushNotificationTests.vcxproj.filters @@ -18,9 +18,6 @@ Header Files - - Header Files - Source Files @@ -35,9 +32,6 @@ Source Files - - Source Files - Source Files @@ -48,4 +42,8 @@ + + + + \ No newline at end of file diff --git a/test/PushNotificationTests/Shared.cpp b/test/PushNotificationTests/Shared.cpp deleted file mode 100644 index 6d8d1bb28c..0000000000 --- a/test/PushNotificationTests/Shared.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See LICENSE in the project root for license information. -#include -#include -#include "Shared.h" - -using namespace WEX::Common; -using namespace WEX::Logging; -using namespace WEX::TestExecution; - -using namespace winrt; -using namespace winrt::Windows::ApplicationModel; -using namespace winrt::Windows::ApplicationModel::Activation; -using namespace winrt::Windows::Foundation; -using namespace winrt::Windows::Foundation::Collections; -using namespace winrt::Windows::Management::Deployment; -using namespace winrt::Windows::Storage; -using namespace winrt::Windows::System; - -namespace Test::PushNotifications -{ - void InstallPackage(const std::wstring& packagePath) - { - // Deploy packaged app to register handler through the manifest. - PackageManager manager; - IVector depPackagePaths; - auto result = manager.AddPackageAsync(Uri(packagePath), depPackagePaths, - DeploymentOptions::ForceApplicationShutdown).get(); - auto errorText = result.ErrorText(); - auto errorCode = result.ExtendedErrorCode(); - VERIFY_SUCCEEDED(errorCode, errorText.c_str()); - } - - void UninstallPackage(const std::wstring& packageFullName) - { - // Deploy packaged app to register handler through the manifest. - PackageManager manager; - IVector depPackagePaths; - auto result = manager.RemovePackageAsync(packageFullName).get(); - auto errorText = result.ErrorText(); - auto errorCode = result.ExtendedErrorCode(); - VERIFY_SUCCEEDED(errorCode, errorText.c_str()); - } -} diff --git a/test/PushNotificationTests/Shared.h b/test/PushNotificationTests/Shared.h deleted file mode 100644 index 428ac939ce..0000000000 --- a/test/PushNotificationTests/Shared.h +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See LICENSE in the project root for license information. -#pragma once - -namespace Test::PushNotifications -{ - void InstallPackage(const std::wstring& packagePath); - void UninstallPackage(const std::wstring& packageFullName); -} diff --git a/test/inc/ProjectReunion.Test.Package.h b/test/inc/ProjectReunion.Test.Package.h index 8f91fc5a0a..c242559c5e 100644 --- a/test/inc/ProjectReunion.Test.Package.h +++ b/test/inc/ProjectReunion.Test.Package.h @@ -267,28 +267,24 @@ constexpr PCWSTR GetCurrentArchitectureAsString() namespace Test::Packages::WapProj { - inline void AddPackage(PCWSTR packageDirName, PCWSTR packageName, PCWSTR packageVersion) + inline void AddPackage(const PCWSTR& packageDirName, const PCWSTR& packageName, const PCWSTR& packageExtension) { - auto msix(::Test::FileSystem::GetSolutionOutDirPath()); - msix /= packageDirName; - msix /= packageName; - msix += "_"; - msix += packageVersion; - msix += "_"; - msix += GetCurrentArchitectureAsString(); - msix += ".msix"; - auto msixUri = winrt::Windows::Foundation::Uri(msix.c_str()); + auto packagePath(::Test::FileSystem::GetSolutionOutDirPath()); + packagePath /= packageDirName; + packagePath /= packageName; + packagePath += packageExtension; + auto packagePathUri = winrt::Windows::Foundation::Uri(packagePath.c_str()); // Install the package winrt::Windows::Management::Deployment::PackageManager packageManager; auto options{ winrt::Windows::Management::Deployment::DeploymentOptions::None }; - auto deploymentResult{ packageManager.AddPackageAsync(msixUri, nullptr, options).get() }; - VERIFY_SUCCEEDED(deploymentResult.ExtendedErrorCode(), WEX::Common::String().Format(L"AddPackageAsync('%s') = 0x%0X %s", msix.c_str(), deploymentResult.ExtendedErrorCode(), deploymentResult.ErrorText().c_str())); + auto deploymentResult{ packageManager.AddPackageAsync(packagePathUri, nullptr, options).get() }; + VERIFY_SUCCEEDED(deploymentResult.ExtendedErrorCode(), WEX::Common::String().Format(L"AddPackageAsync('%s') = 0x%0X %s", packagePath.c_str(), deploymentResult.ExtendedErrorCode(), deploymentResult.ErrorText().c_str())); } - inline void AddPackage(PCWSTR packageDirName, PCWSTR packageVersion) + inline void AddPackage(PCWSTR packageDirName) { - AddPackage(packageDirName, packageDirName, packageVersion); + AddPackage(packageDirName, packageDirName, L".msix"); } } #endif // __PROJECTREUNION_TEST_PACKAGE_H From d8d8388b603d50903c92d74fdf64753cd72ee9b3 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Thu, 3 Jun 2021 17:19:17 -0700 Subject: [PATCH 35/53] Added nuget build files --- .../ProjectReunion-CreateNugetPackage-Job.yml | 3 ++- build/CopyFilesToStagingDir.ps1 | 6 ++++- .../Microsoft.Windows.PushNotifications.xml | 8 +++++++ .../ProjectReunion-Nuget-Native.WinRt.props | 5 ++++ .../ProjectReunion-Nuget-Native.targets | 7 ++++++ test/PushNotificationTests/APITests.cpp | 10 ++++---- test/inc/ProjectReunion.Test.Package.h | 24 +------------------ 7 files changed, 32 insertions(+), 31 deletions(-) create mode 100644 build/NuSpecs/Intellisense/Microsoft.Windows.PushNotifications.xml diff --git a/build/AzurePipelinesTemplates/ProjectReunion-CreateNugetPackage-Job.yml b/build/AzurePipelinesTemplates/ProjectReunion-CreateNugetPackage-Job.yml index 03b87cc19e..18b9ae8ab7 100644 --- a/build/AzurePipelinesTemplates/ProjectReunion-CreateNugetPackage-Job.yml +++ b/build/AzurePipelinesTemplates/ProjectReunion-CreateNugetPackage-Job.yml @@ -62,7 +62,8 @@ jobs: Copy-Item -Path "$targetsFilePath\AppxManifest.xml" -Destination "$fullpackagePath\AppxManifest.xml" Copy-Item -Path "$targetsFilePath\Intellisense\Microsoft.Windows.AppLifecycle.xml" -Destination "$fullpackagePath\lib\uap10.0\Microsoft.Windows.AppLifecycle.xml" - Copy-Item -Path "$targetsFilePath\Intellisense\Microsoft.Windows.ApplicationModel.DynamicDependency.xml" -Destination "$fullpackagePath\lib\uap10.0\Microsoft.Windows.ApplicationModel.DynamicDependency.xml" + Copy-Item -Path "$targetsFilePath\Intellisense\Microsoft.ApplicationModel.DynamicDependency.xml" -Destination "$fullpackagePath\lib\uap10.0\Microsoft.ApplicationModel.DynamicDependency.xml" + Copy-Item -Path "$targetsFilePath\Intellisense\Microsoft.Windows.PushNotifications.xml" -Destination "$fullpackagePath\lib\uap10.0\Microsoft.Windows.PushNotifications.xml" # - script: | # dir /s $(Build.SourcesDirectory) diff --git a/build/CopyFilesToStagingDir.ps1 b/build/CopyFilesToStagingDir.ps1 index 457cc55b7c..758d489b32 100644 --- a/build/CopyFilesToStagingDir.ps1 +++ b/build/CopyFilesToStagingDir.ps1 @@ -38,7 +38,8 @@ PublishFile $OverrideDir\DynamicDependency-Override.json $FullPublishDir\ PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.ProjectReunion.dll $FullPublishDir\Microsoft.ProjectReunion\ PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.ProjectReunion.lib $FullPublishDir\Microsoft.ProjectReunion\ PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.Windows.AppLifecycle.winmd $FullPublishDir\Microsoft.ProjectReunion\ -PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.Windows.ApplicationModel.DynamicDependency.winmd $FullPublishDir\Microsoft.ProjectReunion\ +PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.Windows.PushNotifications.winmd $FullPublishDir\Microsoft.ProjectReunion\ +PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.ApplicationModel.DynamicDependency.winmd $FullPublishDir\Microsoft.ProjectReunion\ PublishFile $FullBuildOutput\ProjectReunion_DLL\MsixDynamicDependency.h $FullPublishDir\Microsoft.ProjectReunion\ PublishFile $FullBuildOutput\ProjectReunion_DLL\wil_msixdynamicdependency.h $FullPublishDir\Microsoft.ProjectReunion\ # @@ -114,12 +115,15 @@ PublishFile $FullBuildOutput\DynamicDependencyLifetimeManager.ProxyStub\DynamicD # # WinMD for UWP apps PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.Windows.AppLifecycle.winmd $NugetDir\lib\uap10.0 +PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.Windows.PushNotifications.winmd $NugetDir\lib\uap10.0 # # Native (not managed, no MSIX) PublishFile $FullBuildOutput\ProjectReunion_BootstrapDLL\Microsoft.ProjectReunion.Bootstrap.dll $NugetDir\runtimes\lib\native\$Platform PublishFile $FullBuildOutput\ProjectReunion_BootstrapDLL\Microsoft.ProjectReunion.Bootstrap.pdb $NugetDir\runtimes\lib\native\$Platform PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.Windows.AppLifecycle.winmd $NugetDir\lib\native PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.Windows.ApplicationModel.DynamicDependency.winmd $NugetDir\lib\native +PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.Windows.PushNotifications.winmd $NugetDir\lib\native + # # C#/WinRT Projections # diff --git a/build/NuSpecs/Intellisense/Microsoft.Windows.PushNotifications.xml b/build/NuSpecs/Intellisense/Microsoft.Windows.PushNotifications.xml new file mode 100644 index 0000000000..3322296f6e --- /dev/null +++ b/build/NuSpecs/Intellisense/Microsoft.Windows.PushNotifications.xml @@ -0,0 +1,8 @@ + + + + Microsoft.Windows.PushNotifications + + + + diff --git a/build/NuSpecs/ProjectReunion-Nuget-Native.WinRt.props b/build/NuSpecs/ProjectReunion-Nuget-Native.WinRt.props index ebe1935c96..0601de8e68 100644 --- a/build/NuSpecs/ProjectReunion-Nuget-Native.WinRt.props +++ b/build/NuSpecs/ProjectReunion-Nuget-Native.WinRt.props @@ -20,6 +20,11 @@ $(MSBuildThisFileDirectory)..\..\runtimes\win10-$(_ProjectReunionFoundationPlatform)\native\Microsoft.ProjectReunion.dll true + + $(MSBuildThisFileDirectory)..\..\lib\uap10.0\Microsoft.Windows.PushNotifications.winmd + $(MSBuildThisFileDirectory)..\..\runtimes\win10-$(_ProjectReunionFoundationPlatform)\native\Microsoft.ProjectReunion.dll + true + diff --git a/build/NuSpecs/ProjectReunion-Nuget-Native.targets b/build/NuSpecs/ProjectReunion-Nuget-Native.targets index 8c0b88c052..f40da59aa1 100644 --- a/build/NuSpecs/ProjectReunion-Nuget-Native.targets +++ b/build/NuSpecs/ProjectReunion-Nuget-Native.targets @@ -23,4 +23,11 @@ + + + false + Microsoft.ProjectReunion.dll + + + diff --git a/test/PushNotificationTests/APITests.cpp b/test/PushNotificationTests/APITests.cpp index 1dd7b0536c..dfcafc4302 100644 --- a/test/PushNotificationTests/APITests.cpp +++ b/test/PushNotificationTests/APITests.cpp @@ -33,18 +33,16 @@ namespace Test::PushNotifications TEST_CLASS_PROPERTY(L"RunAs:Class", L"RestrictedUser") END_TEST_CLASS() - static PCWSTR GetDeploymentDir() + static std::filesystem::path GetDeploymentDir() { WEX::Common::String testDeploymentDir; WEX::TestExecution::RuntimeParameters::TryGetValue(L"TestDeploymentDir", testDeploymentDir); return reinterpret_cast(testDeploymentDir.GetBuffer()); } - static std::filesystem::path GetTestPackageFile() + static PCWSTR GetTestPackageFile() { - auto filename{ std::filesystem::path(GetDeploymentDir()) }; - filename /= L"PushNotificationsTestAppPackage"; - return filename; + return L"PushNotificationsTestAppPackage"; } static PCWSTR GetTestPackageFullName() @@ -57,7 +55,7 @@ namespace Test::PushNotifications try { TP::AddPackage_ProjectReunionFramework(); // Installs PRfwk - TP::WapProj::AddPackage(L"PushNotificationTests", L"PushNotificationsTestAppPackage", L".msix"); // Installs PushNotificationsTestApp.msix + TP::WapProj::AddPackage(GetDeploymentDir(), GetTestPackageFile(), L".msix"); // Installs PushNotificationsTestApp.msix } catch (...) { diff --git a/test/inc/ProjectReunion.Test.Package.h b/test/inc/ProjectReunion.Test.Package.h index c242559c5e..201d91ea84 100644 --- a/test/inc/ProjectReunion.Test.Package.h +++ b/test/inc/ProjectReunion.Test.Package.h @@ -250,27 +250,10 @@ namespace Test::Packages } } -constexpr PCWSTR GetCurrentArchitectureAsString() -{ -#if defined(_M_X64) - return L"x64"; -#elif defined(_M_IX86) - return L"x86"; -#elif defined(_M_ARM64) - return L"arm64"; -#elif defined(_M_ARM) - return L"arm"; -#else -# error "Unknown processor architecture" -#endif -} - namespace Test::Packages::WapProj { - inline void AddPackage(const PCWSTR& packageDirName, const PCWSTR& packageName, const PCWSTR& packageExtension) + inline void AddPackage(std::filesystem::path packagePath, const PCWSTR& packageName, const PCWSTR& packageExtension) { - auto packagePath(::Test::FileSystem::GetSolutionOutDirPath()); - packagePath /= packageDirName; packagePath /= packageName; packagePath += packageExtension; auto packagePathUri = winrt::Windows::Foundation::Uri(packagePath.c_str()); @@ -281,10 +264,5 @@ namespace Test::Packages::WapProj auto deploymentResult{ packageManager.AddPackageAsync(packagePathUri, nullptr, options).get() }; VERIFY_SUCCEEDED(deploymentResult.ExtendedErrorCode(), WEX::Common::String().Format(L"AddPackageAsync('%s') = 0x%0X %s", packagePath.c_str(), deploymentResult.ExtendedErrorCode(), deploymentResult.ErrorText().c_str())); } - - inline void AddPackage(PCWSTR packageDirName) - { - AddPackage(packageDirName, packageDirName, L".msix"); - } } #endif // __PROJECTREUNION_TEST_PACKAGE_H From 5bf3d51c400ec293e9498c93a001219c7909a80b Mon Sep 17 00:00:00 2001 From: Daniel Ayala Date: Thu, 3 Jun 2021 18:47:06 -0700 Subject: [PATCH 36/53] Removed unnecessary Create functions from IDL --- .../PushNotificationBackgroundTask.cpp | 2 +- .../PushNotificationChannel.cpp | 3 ++- .../PushNotificationReceivedEventArgs.cpp | 10 ---------- .../PushNotificationReceivedEventArgs.h | 16 +++------------- dev/PushNotifications/PushNotifications.idl | 6 ------ 5 files changed, 6 insertions(+), 31 deletions(-) diff --git a/dev/PushNotifications/PushNotificationBackgroundTask.cpp b/dev/PushNotifications/PushNotificationBackgroundTask.cpp index 7a8f1d41ee..2cb551d91f 100644 --- a/dev/PushNotifications/PushNotificationBackgroundTask.cpp +++ b/dev/PushNotifications/PushNotificationBackgroundTask.cpp @@ -25,7 +25,7 @@ wil::unique_handle g_waitHandleForArgs = wil::unique_handle(CreateEvent(nullptr, void PushNotificationBackgroundTask::Run(winrt::IBackgroundTaskInstance const& taskInstance) { auto appProperties = winrt::CoreApplication::Properties(); - winrt::PushNotificationReceivedEventArgs activatedEventArgs = winrt::PushNotificationReceivedEventArgs::CreateFromBackgroundTaskInstance(taskInstance); + winrt::PushNotificationReceivedEventArgs activatedEventArgs = winrt::make(taskInstance); appProperties.Insert(ACTIVATED_EVENT_ARGS_KEY, activatedEventArgs); SetEvent(g_waitHandleForArgs.get()); diff --git a/dev/PushNotifications/PushNotificationChannel.cpp b/dev/PushNotifications/PushNotificationChannel.cpp index 11ef2ddee1..b454190be0 100644 --- a/dev/PushNotifications/PushNotificationChannel.cpp +++ b/dev/PushNotifications/PushNotificationChannel.cpp @@ -6,6 +6,7 @@ #include "Microsoft.Windows.PushNotifications.PushNotificationChannel.g.cpp" #include #include +#include "PushNotificationReceivedEventArgs.h" namespace winrt::Windows { @@ -52,7 +53,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation auto strong = weak_self.get(); if (strong) { - handler(*strong, PushNotificationReceivedEventArgs::CreateFromPushNotificationReceivedEventArgs(args)); + handler(*strong, winrt::make(args)); }; }); } diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp index 8a256b5860..9db256b051 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.cpp @@ -27,16 +27,6 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation PushNotificationReceivedEventArgs::PushNotificationReceivedEventArgs(winrt::PushNotificationReceivedEventArgs const& args): m_args(args), m_rawNotification(args.RawNotification().ContentBytes()) {} - winrt::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs PushNotificationReceivedEventArgs::CreateFromBackgroundTaskInstance(winrt::IBackgroundTaskInstance const& backgroundTask) - { - return winrt::make(backgroundTask); - } - - winrt::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs PushNotificationReceivedEventArgs::CreateFromPushNotificationReceivedEventArgs(winrt::PushNotificationReceivedEventArgs const& args) - { - return winrt::make(args); - } - winrt::com_array PushNotificationReceivedEventArgs::Payload() { auto rawNotificationData = m_rawNotification.data(); diff --git a/dev/PushNotifications/PushNotificationReceivedEventArgs.h b/dev/PushNotifications/PushNotificationReceivedEventArgs.h index 116900f845..017b1f2f08 100644 --- a/dev/PushNotifications/PushNotificationReceivedEventArgs.h +++ b/dev/PushNotifications/PushNotificationReceivedEventArgs.h @@ -1,7 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See LICENSE in the project root for license information. - -#pragma once +#pragma once #include "Microsoft.Windows.PushNotifications.PushNotificationReceivedEventArgs.g.h" namespace winrt::Microsoft::Windows::PushNotifications::implementation @@ -9,12 +6,11 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation struct PushNotificationReceivedEventArgs : PushNotificationReceivedEventArgsT { PushNotificationReceivedEventArgs() = delete; + PushNotificationReceivedEventArgs(winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance const& backgroundTask); PushNotificationReceivedEventArgs(winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs const& args); - static Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs CreateFromBackgroundTaskInstance(winrt::Windows::ApplicationModel::Background::IBackgroundTaskInstance const& backgroundTask); - static Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs CreateFromPushNotificationReceivedEventArgs(winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs const& args); - winrt::com_array Payload(); + com_array Payload(); winrt::Windows::ApplicationModel::Background::BackgroundTaskDeferral GetDeferral(); winrt::event_token Canceled(winrt::Windows::ApplicationModel::Background::BackgroundTaskCanceledEventHandler const& handler); void Canceled(winrt::event_token const& token) noexcept; @@ -27,9 +23,3 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation const winrt::Windows::Networking::PushNotifications::PushNotificationReceivedEventArgs m_args = nullptr; }; } -namespace winrt::Microsoft::Windows::PushNotifications::factory_implementation -{ - struct PushNotificationReceivedEventArgs : PushNotificationReceivedEventArgsT - { - }; -} diff --git a/dev/PushNotifications/PushNotifications.idl b/dev/PushNotifications/PushNotifications.idl index 2926f90c09..dd286ba4e6 100644 --- a/dev/PushNotifications/PushNotifications.idl +++ b/dev/PushNotifications/PushNotifications.idl @@ -7,12 +7,6 @@ namespace Microsoft.Windows.PushNotifications // Event args for the Push payload. runtimeclass PushNotificationReceivedEventArgs { - // Initialize using the IBackgroundInstance: used specifically for the Background Activation scenario - static PushNotificationReceivedEventArgs CreateFromBackgroundTaskInstance(Windows.ApplicationModel.Background.IBackgroundTaskInstance backgroundTask); - - // Initialize using the PushNotificationEventArgs from Windows: used specifically for in-memory event handling when app is already in foreground - static PushNotificationReceivedEventArgs CreateFromPushNotificationReceivedEventArgs(Windows.Networking.PushNotifications.PushNotificationReceivedEventArgs args); - // The Push payload byte[] Payload { get; }; From e90e608f967fd82a97b8b5d946720e55a60b7d59 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Fri, 4 Jun 2021 10:34:22 -0700 Subject: [PATCH 37/53] Added multiple channel close test --- .../PushNotificationBackgroundTask.h | 12 +------ test/PushNotificationTests/APITests.cpp | 5 +++ .../PushNotificationsTestApp/main.cpp | 36 ++++++++++++++++++- 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/dev/PushNotifications/PushNotificationBackgroundTask.h b/dev/PushNotifications/PushNotificationBackgroundTask.h index f5c95e7f0d..9f763af7cb 100644 --- a/dev/PushNotifications/PushNotificationBackgroundTask.h +++ b/dev/PushNotifications/PushNotificationBackgroundTask.h @@ -3,8 +3,6 @@ #include -static long g_backgroundTaskServerLock = 0; - struct PushNotificationBackgroundTask : winrt::implements { PushNotificationBackgroundTask() {} @@ -26,16 +24,8 @@ struct PushNotificationBackgroundTaskFactory : winrt::implements().as(interfaceId, object); } - HRESULT __stdcall LockServer(BOOL lock) noexcept final + HRESULT __stdcall LockServer(BOOL) noexcept final { - if (lock) - { - InterlockedIncrement(&g_backgroundTaskServerLock); - } - else - { - InterlockedDecrement(&g_backgroundTaskServerLock); - } return S_OK; } }; diff --git a/test/PushNotificationTests/APITests.cpp b/test/PushNotificationTests/APITests.cpp index dfcafc4302..92e94d1121 100644 --- a/test/PushNotificationTests/APITests.cpp +++ b/test/PushNotificationTests/APITests.cpp @@ -146,6 +146,11 @@ namespace Test::PushNotifications RunTest(L"ChannelRequestUsingRemoteId", c_pushTestChannelWait); } + TEST_METHOD(MultipleChannelClose) + { + RunTest(L"MultipleChannelClose", c_pushTestChannelWait); + } + TEST_METHOD(MultipleChannelRequestUsingSameRemoteId) { RunTest(L"MultipleChannelRequestUsingSameRemoteId", c_pushTestChannelWait); diff --git a/test/TestApps/PushNotificationsTestApp/main.cpp b/test/TestApps/PushNotificationsTestApp/main.cpp index dd90f76dc7..6cf2a83d86 100644 --- a/test/TestApps/PushNotificationsTestApp/main.cpp +++ b/test/TestApps/PushNotificationsTestApp/main.cpp @@ -16,7 +16,8 @@ using namespace winrt::Windows::ApplicationModel::Background; // BackgroundTask enum UnitTest { channelRequestUsingNullRemoteId, channelRequestUsingRemoteId, multipleChannelRequestUsingSameRemoteId, multipleChannelRequestUsingMultipleRemoteId, activatorTest, registerActivatorNullDetails, - registerActivatorNullClsid, unregisterActivatorNullToken, unregisterActivatorNullBackgroundRegistration, multipleRegisterActivatorTest + registerActivatorNullClsid, unregisterActivatorNullToken, unregisterActivatorNullBackgroundRegistration, + multipleRegisterActivatorTest, multipleChannelClose }; static std::map switchMapping; @@ -39,6 +40,7 @@ void initUnitTestMapping() { switchMapping["ChannelRequestUsingNullRemoteId"] = UnitTest::channelRequestUsingNullRemoteId; switchMapping["ChannelRequestUsingRemoteId"] = UnitTest::channelRequestUsingRemoteId; + switchMapping["MultipleChannelClose"] = UnitTest::multipleChannelClose; switchMapping["MultipleChannelRequestUsingSameRemoteId"] = UnitTest::multipleChannelRequestUsingSameRemoteId; switchMapping["MultipleChannelRequestUsingMultipleRemoteId"] = UnitTest::multipleChannelRequestUsingMultipleRemoteId; switchMapping["ActivatorTest"] = UnitTest::activatorTest; @@ -93,6 +95,35 @@ bool ChannelRequestUsingRemoteId() return channelOperationResult == S_OK; } +bool MultipleChannelClose() +{ + auto channelOperation = PushNotificationManager::CreateChannelAsync(remoteId1); + if (channelOperation.wait_for(std::chrono::seconds(300)) != AsyncStatus::Completed) + { + channelOperation.Cancel(); + return false; // timed out or failed + } + + auto result = channelOperation.GetResults(); + auto status = result.Status(); + if (status != PushNotificationChannelStatus::CompletedSuccess) + { + return false; // did not produce a channel + } + + result.Channel().Close(); + try + { + result.Channel().Close(); + } + catch (...) + { + auto channelRequestException = hresult_error(to_hresult()); + return channelRequestException.code() == WPN_E_CHANNEL_CLOSED; + } + return false; +} + bool MultipleChannelRequestUsingSameRemoteId() { @@ -231,6 +262,9 @@ bool runUnitTest(std::string unitTest) case UnitTest::channelRequestUsingRemoteId: return ChannelRequestUsingRemoteId(); + case UnitTest::multipleChannelClose: + return MultipleChannelClose(); + case UnitTest::multipleChannelRequestUsingSameRemoteId: return MultipleChannelRequestUsingSameRemoteId(); From 38b9b939bbb6b250965258520fd5f837b08f7fd1 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Fri, 4 Jun 2021 12:22:53 -0700 Subject: [PATCH 38/53] Implement LockServer --- dev/PushNotifications/PushNotificationBackgroundTask.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/dev/PushNotifications/PushNotificationBackgroundTask.h b/dev/PushNotifications/PushNotificationBackgroundTask.h index 9f763af7cb..01590ed5f8 100644 --- a/dev/PushNotifications/PushNotificationBackgroundTask.h +++ b/dev/PushNotifications/PushNotificationBackgroundTask.h @@ -24,8 +24,16 @@ struct PushNotificationBackgroundTaskFactory : winrt::implements().as(interfaceId, object); } - HRESULT __stdcall LockServer(BOOL) noexcept final + HRESULT __stdcall LockServer(BOOL fLock) noexcept final { + if (fLock) + { + ++winrt::get_module_lock(); + } + else + { + --winrt::get_module_lock(); + } return S_OK; } }; From 735ae79043eb17bd389e0e479e51d32b18f9b998 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Wed, 9 Jun 2021 01:06:45 -0700 Subject: [PATCH 39/53] Fixing nits --- .../PushNotificationChannel.cpp | 2 +- test/PushNotificationTests/APITests.cpp | 17 +- test/PushNotificationTests/pch.h | 3 +- .../PushNotificationsDemoApp/main.cpp | 20 +-- .../Package.appxmanifest | 8 +- .../PushNotificationsTestApp/main.cpp | 152 ++++++------------ .../Package.appxmanifest | 2 +- test/inc/TestDef.h | 2 +- 8 files changed, 78 insertions(+), 128 deletions(-) diff --git a/dev/PushNotifications/PushNotificationChannel.cpp b/dev/PushNotifications/PushNotificationChannel.cpp index b454190be0..990f362c98 100644 --- a/dev/PushNotifications/PushNotificationChannel.cpp +++ b/dev/PushNotifications/PushNotificationChannel.cpp @@ -41,7 +41,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation auto channelCloseException = hresult_error(to_hresult()); if (channelCloseException.code() != HRESULT_FROM_WIN32(ERROR_NOT_FOUND)) { - throw channelCloseException; + throw hresult_error(to_hresult()); } } } diff --git a/test/PushNotificationTests/APITests.cpp b/test/PushNotificationTests/APITests.cpp index 92e94d1121..13f35ff04c 100644 --- a/test/PushNotificationTests/APITests.cpp +++ b/test/PushNotificationTests/APITests.cpp @@ -23,7 +23,7 @@ namespace Test::PushNotifications { private: wil::unique_event m_failed; - wil::unique_handle m_processHandle; + wil::unique_process_handle m_processHandle; winrt::com_ptr m_testAppLauncher; public: @@ -90,22 +90,19 @@ namespace Test::PushNotifications { VERIFY_IS_TRUE(TP::IsPackageRegistered_ProjectReunionFramework()); - if (m_processHandle) - { - m_processHandle.reset(); - } + m_processHandle.reset(); return true; } void RunTest(const PCWSTR& testName, const int& waitTime) { DWORD processId; - VERIFY_SUCCEEDED(m_testAppLauncher.get()->ActivateApplication(L"PushNotificationsTestAppPackage_8wekyb3d8bbwe!App", testName, AO_NONE, &processId)); + VERIFY_SUCCEEDED(m_testAppLauncher->ActivateApplication(L"PushNotificationsTestAppPackage_8wekyb3d8bbwe!App", testName, AO_NONE, &processId)); - m_processHandle = wil::unique_handle(OpenProcess(SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processId)); + m_processHandle.reset(OpenProcess(SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processId)); VERIFY_IS_TRUE(m_processHandle.is_valid()); - VERIFY_ARE_EQUAL(WaitForSingleObject(m_processHandle.get(), waitTime), WAIT_OBJECT_0); + VERIFY_IS_TRUE(wil::handle_wait(m_processHandle.get(), waitTime)); DWORD exitCode; VERIFY_WIN32_BOOL_SUCCEEDED(GetExitCodeProcess(m_processHandle.get(), &exitCode)); @@ -114,7 +111,7 @@ namespace Test::PushNotifications TEST_METHOD(BackgroundActivation) { - RunTest(nullptr, c_pushTestWait); // Need to launch one time to enable background activation. + RunTest(L"BackgroundActivationTest", c_pushTestWait); // Need to launch one time to enable background activation. auto LocalBackgroundTask = winrt::create_instance(c_comServerId, CLSCTX_ALL); auto mockBackgroundTaskInstance = winrt::make(); @@ -123,7 +120,7 @@ namespace Test::PushNotifications TEST_METHOD(MultipleBackgroundActivation) { - RunTest(nullptr, c_pushTestWait); // Need to launch one time to enable background activation. + RunTest(L"BackgroundActivationTest", c_pushTestWait); // Need to launch one time to enable background activation. auto LocalBackgroundTask1 = winrt::create_instance(c_comServerId, CLSCTX_ALL); auto mockBackgroundTaskInstance1 = winrt::make(); diff --git a/test/PushNotificationTests/pch.h b/test/PushNotificationTests/pch.h index 16cddcc86c..bdfe7c4dac 100644 --- a/test/PushNotificationTests/pch.h +++ b/test/PushNotificationTests/pch.h @@ -3,7 +3,6 @@ #ifndef PCH_H #define PCH_H -#endif //PCH_H #include @@ -37,3 +36,5 @@ #include namespace TP = ::Test::Packages; + +#endif //PCH_H diff --git a/test/TestApps/PushNotificationsDemoApp/main.cpp b/test/TestApps/PushNotificationsDemoApp/main.cpp index 65b19588c3..e205ca52a9 100644 --- a/test/TestApps/PushNotificationsDemoApp/main.cpp +++ b/test/TestApps/PushNotificationsDemoApp/main.cpp @@ -10,15 +10,11 @@ using namespace winrt::Microsoft::Windows::AppLifecycle; using namespace winrt::Microsoft::Windows::PushNotifications; -using namespace winrt; -using namespace winrt::Windows::Storage; -using namespace winrt::Windows::Storage::Streams; -using namespace winrt::Windows::Foundation; using namespace winrt::Windows::ApplicationModel::Activation; using namespace winrt::Windows::ApplicationModel::Background; // BackgroundTask APIs - -time_t ltime; -char buf[SIZE]; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Storage; +using namespace winrt::Windows::Storage::Streams; winrt::Windows::Foundation::IAsyncOperation RequestChannelAsync() { @@ -96,6 +92,9 @@ winrt::Microsoft::Windows::PushNotifications::PushNotificationChannel RequestCha int main() { + time_t ltime; + char buf[SIZE]; + time(<ime); ctime_s(buf, sizeof buf, <ime); std::cout << "Project Reunion Push Notification Test App: " << buf << std::endl; @@ -121,9 +120,10 @@ int main() std::string payloadString(payload.begin(), payload.end()); std::cout << "Push notification content received from BACKGROUND: " << payloadString << std::endl << std::endl; std::cout << "Press 'Enter' to exit the App." << std::endl; - std::cin.ignore(); - // Call Complete on the deferral as good practise: Needed mainly for low power usage + + // Call Complete on the deferral as good practice: Needed mainly for low power usage deferral.Complete(); + std::cin.ignore(); } else if (kind == ExtendedActivationKind::Launch) { @@ -138,6 +138,6 @@ int main() std::cin.ignore(); } - PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationOption::ComActivator); + PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); return 0; } diff --git a/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest b/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest index 67f9bf3087..ca577e6345 100644 --- a/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest +++ b/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest @@ -13,8 +13,8 @@ Version="1.0.0.0" /> - MSIXPackager - purifoypaul + Push Notifications Win32 Demo App + Microsoft Corporation Images\StoreLogo.png @@ -33,8 +33,8 @@ Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$"> diff --git a/test/TestApps/PushNotificationsTestApp/main.cpp b/test/TestApps/PushNotificationsTestApp/main.cpp index 6cf2a83d86..5cf1ccd681 100644 --- a/test/TestApps/PushNotificationsTestApp/main.cpp +++ b/test/TestApps/PushNotificationsTestApp/main.cpp @@ -4,68 +4,34 @@ #include #include #include // we need this for BackgroundTask APIs + +using namespace winrt; using namespace winrt::Microsoft::Windows::AppLifecycle; using namespace winrt::Microsoft::Windows::PushNotifications; -using namespace winrt; -using namespace winrt::Windows::Storage; -using namespace winrt::Windows::Storage::Streams; -using namespace winrt::Windows::Foundation; using namespace winrt::Windows::ApplicationModel::Activation; using namespace winrt::Windows::ApplicationModel::Background; // BackgroundTask APIs +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Storage; +using namespace winrt::Windows::Storage::Streams; -enum UnitTest { - channelRequestUsingNullRemoteId, channelRequestUsingRemoteId, multipleChannelRequestUsingSameRemoteId, - multipleChannelRequestUsingMultipleRemoteId, activatorTest, registerActivatorNullDetails, - registerActivatorNullClsid, unregisterActivatorNullToken, unregisterActivatorNullBackgroundRegistration, - multipleRegisterActivatorTest, multipleChannelClose -}; - -static std::map switchMapping; winrt::guid remoteId1(L"a2e4a323-b518-4799-9e80-0b37aeb0d225"); winrt::guid remoteId2(L"CA1A4AB2-AC1D-4EFC-A132-E5A191CA285A"); winrt::guid remoteId3(L"40FCE789-C6BF-4F47-A6CF-6B9C1DCE31BA"); + PushNotificationRegistrationToken appToken = nullptr; PushNotificationRegistrationToken fakeToken = nullptr; -void signalPhase(const std::wstring& phaseEventName) -{ - wil::unique_event phaseEvent; - if (phaseEvent.try_open(phaseEventName.c_str(), EVENT_MODIFY_STATE, false)) - { - phaseEvent.SetEvent(); - } -} - -void initUnitTestMapping() -{ - switchMapping["ChannelRequestUsingNullRemoteId"] = UnitTest::channelRequestUsingNullRemoteId; - switchMapping["ChannelRequestUsingRemoteId"] = UnitTest::channelRequestUsingRemoteId; - switchMapping["MultipleChannelClose"] = UnitTest::multipleChannelClose; - switchMapping["MultipleChannelRequestUsingSameRemoteId"] = UnitTest::multipleChannelRequestUsingSameRemoteId; - switchMapping["MultipleChannelRequestUsingMultipleRemoteId"] = UnitTest::multipleChannelRequestUsingMultipleRemoteId; - switchMapping["ActivatorTest"] = UnitTest::activatorTest; - switchMapping["RegisterActivatorNullDetails"] = UnitTest::registerActivatorNullDetails; - switchMapping["RegisterActivatorNullClsid"] = UnitTest::registerActivatorNullClsid; - switchMapping["UnregisterActivatorNullToken"] = UnitTest::unregisterActivatorNullToken; - switchMapping["UnregisterActivatorNullBackgroundRegistration"] = UnitTest::unregisterActivatorNullBackgroundRegistration; - switchMapping["MultipleRegisterActivatorTest"] = UnitTest::multipleRegisterActivatorTest; -} - bool ChannelRequestUsingNullRemoteId() { - winrt::hresult hr = S_OK; - try { auto channelOperation = PushNotificationManager::CreateChannelAsync(winrt::guid()).get(); } catch (...) { - auto channelRequestException = hresult_error(to_hresult()); - hr = channelRequestException.code(); + return to_hresult() == E_INVALIDARG; } - - return (hr == E_INVALIDARG); + return false; } HRESULT ChannelRequestHelper(IAsyncOperationWithProgress const& channelOperation) @@ -73,7 +39,7 @@ HRESULT ChannelRequestHelper(IAsyncOperationWithProgress const& GetSwitchMapping() +{ + static std::map switchMapping = { + { "ChannelRequestUsingNullRemoteId", &ChannelRequestUsingNullRemoteId }, + { "ChannelRequestUsingRemoteId", &ChannelRequestUsingRemoteId }, + { "MultipleChannelClose", &MultipleChannelClose}, + { "MultipleChannelRequestUsingSameRemoteId", &MultipleChannelRequestUsingSameRemoteId}, + { "MultipleChannelRequestUsingMultipleRemoteId", &MultipleChannelRequestUsingMultipleRemoteId}, + { "RegisterActivatorNullDetails", &RegisterActivatorNullDetails}, + { "RegisterActivatorNullClsid", &RegisterActivatorNullClsid}, + { "UnregisterActivatorNullToken", &UnregisterActivatorNullToken}, + { "UnregisterActivatorNullBackgroundRegistration", &UnregisterActivatorNullBackgroundRegistration}, + { "ActivatorTest", &ActivatorTest}, + { "MultipleRegisterActivatorTest", &MultipleRegisterActivatorTest}, + { "BackgroundActivationTest", &BackgroundActivationTest} + }; + return switchMapping; +} - default: +bool runUnitTest(std::string unitTest) +{ + auto const& switchMapping = GetSwitchMapping(); + auto it = switchMapping.find(unitTest); + if (it == switchMapping.end()) + { return false; } + + return it->second(); } // Cleanup function for exiting test app. @@ -313,7 +266,6 @@ void UnregisterClsid() int main() { - initUnitTestMapping(); bool testResult = false; auto scope_exit = wil::scope_exit([&] { UnregisterClsid(); @@ -342,7 +294,7 @@ int main() auto payload = pushArgs.Payload(); std::wstring payloadString(payload.begin(), payload.end()); - testResult = !payloadString.compare(c_rawNotificationPayload); + testResult = payloadString == c_rawNotificationPayload; } return testResult ? 0 : 1; // We want 0 to be success and 1 failure diff --git a/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest b/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest index c811ee0e06..c5fa3fbd34 100644 --- a/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest +++ b/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest @@ -14,7 +14,7 @@ PushNotificationsTestAppPackage - vemancha + Microsoft Corporation Images\StoreLogo.png diff --git a/test/inc/TestDef.h b/test/inc/TestDef.h index 65957bb20d..8143274f4e 100644 --- a/test/inc/TestDef.h +++ b/test/inc/TestDef.h @@ -18,7 +18,7 @@ static const std::wstring c_testStartupPhaseEventName = L"ReunionTestStartupPhas static const std::wstring c_testInstanceRedirectedPhaseEventName = L"ReunionTestInstanceRedirectedPhaseEventName"; inline const winrt::hstring c_rawNotificationPayload = L""; -inline IID c_comServerId = winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2"); +inline IID c_comServerId = winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2"); // Value from PushNotificationsTestAppPackage ComActivator in appxmanifest. inline IID c_fakeComServerId = winrt::guid("00000000-0000-0000-0000-000000000001"); inline const int c_pushTestWait = 3000; inline const int c_pushTestChannelWait = c_pushTestWait + 300000; // Need to wait 300000ms for channel request + 3000ms for application overhead From 0a89d4d99d0f62e27482668bbcaee15d8d1ee5bd Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Wed, 9 Jun 2021 10:23:41 -0700 Subject: [PATCH 40/53] Added test app changes --- test/TestApps/PushNotificationsDemoApp/main.cpp | 5 +++-- test/TestApps/PushNotificationsTestApp/main.cpp | 14 +++++++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/test/TestApps/PushNotificationsDemoApp/main.cpp b/test/TestApps/PushNotificationsDemoApp/main.cpp index e205ca52a9..22173e40ee 100644 --- a/test/TestApps/PushNotificationsDemoApp/main.cpp +++ b/test/TestApps/PushNotificationsDemoApp/main.cpp @@ -121,7 +121,8 @@ int main() std::cout << "Push notification content received from BACKGROUND: " << payloadString << std::endl << std::endl; std::cout << "Press 'Enter' to exit the App." << std::endl; - // Call Complete on the deferral as good practice: Needed mainly for low power usage + // Call Complete on the deferral when finished processing the payload. + // This removes the override that kept the app running even when the system was in a low power mode. deferral.Complete(); std::cin.ignore(); } @@ -138,6 +139,6 @@ int main() std::cin.ignore(); } - PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); + PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationOption::ComActivator); // Don't unregister PushTrigger because we still want to receive push notifications from background infrastructure. return 0; } diff --git a/test/TestApps/PushNotificationsTestApp/main.cpp b/test/TestApps/PushNotificationsTestApp/main.cpp index 5cf1ccd681..dc7b50c761 100644 --- a/test/TestApps/PushNotificationsTestApp/main.cpp +++ b/test/TestApps/PushNotificationsTestApp/main.cpp @@ -14,9 +14,8 @@ using namespace winrt::Windows::Foundation; using namespace winrt::Windows::Storage; using namespace winrt::Windows::Storage::Streams; -winrt::guid remoteId1(L"a2e4a323-b518-4799-9e80-0b37aeb0d225"); -winrt::guid remoteId2(L"CA1A4AB2-AC1D-4EFC-A132-E5A191CA285A"); -winrt::guid remoteId3(L"40FCE789-C6BF-4F47-A6CF-6B9C1DCE31BA"); +winrt::guid remoteId1(L"a2e4a323-b518-4799-9e80-0b37aeb0d225"); // Generated from ms.portal.azure.com +winrt::guid remoteId2(L"CA1A4AB2-AC1D-4EFC-A132-E5A191CA285A"); // Dummy guid from visual studio guid tool generator PushNotificationRegistrationToken appToken = nullptr; PushNotificationRegistrationToken fakeToken = nullptr; @@ -264,7 +263,7 @@ void UnregisterClsid() } -int main() +int main() try { bool testResult = false; auto scope_exit = wil::scope_exit([&] { @@ -298,4 +297,9 @@ int main() } return testResult ? 0 : 1; // We want 0 to be success and 1 failure -}; +} +catch (...) +{ + std::cout << winrt::to_string(winrt::to_message()) << std::endl; + return 1; // in the event of unhandled test crash +} From fa4e2c6dfd8206c6395a0bcadf9f5b56d3dfb937 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Wed, 9 Jun 2021 14:29:24 -0700 Subject: [PATCH 41/53] Fix unregister token --- test/TestApps/PushNotificationsTestApp/main.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/test/TestApps/PushNotificationsTestApp/main.cpp b/test/TestApps/PushNotificationsTestApp/main.cpp index dc7b50c761..a7c4809c40 100644 --- a/test/TestApps/PushNotificationsTestApp/main.cpp +++ b/test/TestApps/PushNotificationsTestApp/main.cpp @@ -111,7 +111,7 @@ bool MultipleChannelRequestUsingMultipleRemoteId() bool ActivatorTest() { - PushNotificationManager::UnregisterActivator(appToken, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); + PushNotificationManager::UnregisterActivator(std::exchange(appToken, nullptr), PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); try { PushNotificationActivationInfo info( @@ -124,7 +124,7 @@ bool ActivatorTest() return false; } - PushNotificationManager::UnregisterActivator(fakeToken, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); + PushNotificationManager::UnregisterActivator(std::exchange(fakeToken, nullptr), PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); } catch (...) { @@ -201,7 +201,7 @@ bool MultipleRegisterActivatorTest() PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator, c_fakeComServerId); // Fake clsid to test multiple activators - appToken = PushNotificationManager::RegisterActivator(info); + fakeToken = PushNotificationManager::RegisterActivator(info); } catch (...) { @@ -251,14 +251,12 @@ void UnregisterClsid() { if (appToken) { - ::CoRevokeClassObject(static_cast(appToken.Cookie())); - PushNotificationManager::UnregisterActivator(appToken, PushNotificationRegistrationOption::PushTrigger); + PushNotificationManager::UnregisterActivator(appToken, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); } if (fakeToken) { - ::CoRevokeClassObject(static_cast(fakeToken.Cookie())); - PushNotificationManager::UnregisterActivator(fakeToken, PushNotificationRegistrationOption::PushTrigger); + PushNotificationManager::UnregisterActivator(fakeToken, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); } } From ab1ac2b9abfaedf2231fbd3f64109a0cba99f206 Mon Sep 17 00:00:00 2001 From: Sharath Manchala <10109130+sharath2727@users.noreply.github.com> Date: Thu, 10 Jun 2021 08:59:07 -0700 Subject: [PATCH 42/53] Fix nits in createchannelasync API --- dev/PushNotifications/PushNotificationManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp index 0fb93419d5..8ae473cc83 100644 --- a/dev/PushNotifications/PushNotificationManager.cpp +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -33,7 +33,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { inline constexpr auto c_maxBackoff{ 5min }; inline constexpr auto c_initialBackoff{ 60s }; - inline constexpr auto c_backoffFactor{ 60s }; + inline constexpr auto c_backoffIncrement{ 60s }; const HRESULT WNP_E_NOT_CONNECTED = (HRESULT)0x880403E8L; const HRESULT WNP_E_RECONNECTING = (HRESULT)0x880403E9L; @@ -98,7 +98,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation progress(channelStatus); - for (auto backOffTime = c_initialBackoff; ; backOffTime += c_backoffFactor) + for (auto backOffTime = c_initialBackoff; ; backOffTime += c_backoffIncrement) { try { @@ -134,7 +134,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } } - co_await winrt::resume_after(std::chrono::milliseconds(backOffTime)); + co_await winrt::resume_after(backOffTime); } } From 6f55098464dc5b6909f937a4de153bb98fc75548 Mon Sep 17 00:00:00 2001 From: Daniel Ayala Date: Thu, 10 Jun 2021 16:34:27 -0700 Subject: [PATCH 43/53] Addressed comments mostly on Background Activation and the IDL --- .../GetRawNotificationEventArgs.h | 17 ++-------- .../PushNotificationActivationInfo.cpp | 6 ++-- .../PushNotificationActivationInfo.h | 6 ++-- .../PushNotificationBackgroundTask.cpp | 2 +- .../PushNotificationBackgroundTask.h | 3 +- .../PushNotificationManager.cpp | 31 +++++++++---------- .../PushNotificationManager.h | 2 +- .../PushNotificationRegistrationToken.cpp | 4 +-- .../PushNotificationRegistrationToken.h | 6 ++-- dev/PushNotifications/PushNotifications.idl | 19 ++++++------ dev/PushNotifications/externs.h | 4 +-- .../PushNotificationsDemoApp/main.cpp | 6 ++-- .../PushNotificationsTestApp/main.cpp | 21 +++++++------ 13 files changed, 58 insertions(+), 69 deletions(-) diff --git a/dev/PushNotifications/GetRawNotificationEventArgs.h b/dev/PushNotifications/GetRawNotificationEventArgs.h index 1f1b6c8937..58d4518b18 100644 --- a/dev/PushNotifications/GetRawNotificationEventArgs.h +++ b/dev/PushNotifications/GetRawNotificationEventArgs.h @@ -8,24 +8,11 @@ constexpr PCWSTR c_pushContractId = L"Windows.Push"; -using namespace winrt::Windows::ApplicationModel::Core; namespace winrt::Microsoft::Windows::PushNotifications { static winrt::Windows::Foundation::IInspectable Deserialize(winrt::Windows::Foundation::Uri const&) { - if (WaitForSingleObject(g_waitHandleForArgs.get(), 2000) == WAIT_OBJECT_0) - { - auto appProperties = CoreApplication::Properties(); - if (auto foundActivatedEventArgs = appProperties.TryLookup(ACTIVATED_EVENT_ARGS_KEY)) - { - return foundActivatedEventArgs.as(); - } - else - { - return nullptr; - } - } - - winrt::throw_hresult(HRESULT_FROM_WIN32(ERROR_TIMEOUT)); + THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_TIMEOUT), !g_waitHandleForArgs.wait(2000)); + return winrt::Windows::ApplicationModel::Core::CoreApplication::Properties().TryLookup(ACTIVATED_EVENT_ARGS_KEY).as(); } } diff --git a/dev/PushNotifications/PushNotificationActivationInfo.cpp b/dev/PushNotifications/PushNotificationActivationInfo.cpp index 8cd18f6df9..607b2c7b2e 100644 --- a/dev/PushNotifications/PushNotificationActivationInfo.cpp +++ b/dev/PushNotifications/PushNotificationActivationInfo.cpp @@ -15,16 +15,16 @@ namespace winrt namespace winrt::Microsoft::Windows::PushNotifications::implementation { - PushNotificationActivationInfo::PushNotificationActivationInfo(winrt::PushNotificationRegistrationOption const& option, winrt::guid const& taskClsid) : m_option(option), m_taskClsid(taskClsid) {} + PushNotificationActivationInfo::PushNotificationActivationInfo(winrt::PushNotificationRegistrationOptions const& options, winrt::guid const& taskClsid) : m_options(options), m_taskClsid(taskClsid) {} winrt::guid PushNotificationActivationInfo::TaskClsid() { return m_taskClsid; } - winrt::PushNotificationRegistrationOption PushNotificationActivationInfo::Option() + winrt::PushNotificationRegistrationOptions PushNotificationActivationInfo::Options() { - return m_option; + return m_options; } winrt::com_array PushNotificationActivationInfo::GetConditions() diff --git a/dev/PushNotifications/PushNotificationActivationInfo.h b/dev/PushNotifications/PushNotificationActivationInfo.h index 0cd6519d67..aa03c43430 100644 --- a/dev/PushNotifications/PushNotificationActivationInfo.h +++ b/dev/PushNotifications/PushNotificationActivationInfo.h @@ -8,14 +8,14 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { struct PushNotificationActivationInfo : PushNotificationActivationInfoT { - PushNotificationActivationInfo(Microsoft::Windows::PushNotifications::PushNotificationRegistrationOption const& option, winrt::guid const& taskClsid); + PushNotificationActivationInfo(Microsoft::Windows::PushNotifications::PushNotificationRegistrationOptions const& option, winrt::guid const& taskClsid); winrt::guid TaskClsid(); - Microsoft::Windows::PushNotifications::PushNotificationRegistrationOption Option(); + Microsoft::Windows::PushNotifications::PushNotificationRegistrationOptions Options(); winrt::com_array GetConditions(); void SetConditions(array_view conditions); private: - const Microsoft::Windows::PushNotifications::PushNotificationRegistrationOption m_option; + const Microsoft::Windows::PushNotifications::PushNotificationRegistrationOptions m_options; const winrt::guid m_taskClsid; winrt::com_array m_backgroundConditions{}; wil::srwlock m_lock; diff --git a/dev/PushNotifications/PushNotificationBackgroundTask.cpp b/dev/PushNotifications/PushNotificationBackgroundTask.cpp index 2cb551d91f..632d24cf98 100644 --- a/dev/PushNotifications/PushNotificationBackgroundTask.cpp +++ b/dev/PushNotifications/PushNotificationBackgroundTask.cpp @@ -20,7 +20,7 @@ namespace winrt using namespace Windows::ApplicationModel::Core; } -wil::unique_handle g_waitHandleForArgs = wil::unique_handle(CreateEvent(nullptr, FALSE, FALSE, nullptr)); +wil::unique_event g_waitHandleForArgs; void PushNotificationBackgroundTask::Run(winrt::IBackgroundTaskInstance const& taskInstance) { diff --git a/dev/PushNotifications/PushNotificationBackgroundTask.h b/dev/PushNotifications/PushNotificationBackgroundTask.h index 01590ed5f8..fc8b59ad9b 100644 --- a/dev/PushNotifications/PushNotificationBackgroundTask.h +++ b/dev/PushNotifications/PushNotificationBackgroundTask.h @@ -18,11 +18,12 @@ struct PushNotificationBackgroundTask : winrt::implements { - HRESULT __stdcall CreateInstance(_In_opt_ IUnknown* aggregateInterface, _In_ REFIID interfaceId, _Outptr_ VOID** object) noexcept final + HRESULT __stdcall CreateInstance(_In_opt_ IUnknown* aggregateInterface, _In_ REFIID interfaceId, _Outptr_ VOID** object) noexcept final try { RETURN_HR_IF(CLASS_E_NOAGGREGATION, aggregateInterface != nullptr); return winrt::make().as(interfaceId, object); } + CATCH_RETURN() HRESULT __stdcall LockServer(BOOL fLock) noexcept final { diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp index 8ae473cc83..c655b554c0 100644 --- a/dev/PushNotifications/PushNotificationManager.cpp +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -145,14 +145,14 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation GUID taskClsid = details.TaskClsid(); THROW_HR_IF(E_INVALIDARG, taskClsid == GUID_NULL); - auto registrationOption = details.Option(); - THROW_HR_IF(E_INVALIDARG, WI_AreAllFlagsClear(registrationOption, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator)); + auto registrationOptions = details.Options(); + THROW_HR_IF(E_INVALIDARG, WI_AreAllFlagsClear(registrationOptions, PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator)); DWORD cookie = 0; IBackgroundTaskRegistration registeredTask = nullptr; BackgroundTaskBuilder builder = nullptr; - if (WI_IsFlagSet(registrationOption, PushNotificationRegistrationOption::PushTrigger)) + if (WI_IsFlagSet(registrationOptions, PushNotificationRegistrationOptions::PushTrigger)) { winrt::hstring taskClsidStr = winrt::to_hstring(taskClsid); winrt::hstring backgroundTaskFullName = backgroundTaskName + taskClsidStr; @@ -201,19 +201,18 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } } - bool registeredWithCom = false; - bool registeredWithBackgroundTask = false; + BackgroundTaskRegistration registeredTaskFromBuilder = nullptr; auto scopeExitToCleanRegistrations = wil::scope_exit( [&]() { - if (registeredWithCom) + if (cookie > 0) { LOG_IF_FAILED(::CoRevokeClassObject(cookie)); } // Clean the task registration only if it was created during this call - if (registeredWithBackgroundTask) + if (registeredTaskFromBuilder) { registeredTask.Unregister(true); } @@ -221,8 +220,9 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } ); - if (WI_IsFlagSet(registrationOption, PushNotificationRegistrationOption::ComActivator)) + if (WI_IsFlagSet(registrationOptions, PushNotificationRegistrationOptions::ComActivator)) { + g_waitHandleForArgs.create(); THROW_HR_IF_NULL(E_UNEXPECTED, g_waitHandleForArgs); THROW_IF_FAILED(::CoRegisterClassObject( @@ -231,34 +231,31 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie)); - - registeredWithCom = true; } if (builder) { - auto registeredTaskFromBuilder = builder.Register(); - registeredTask = registeredTaskFromBuilder.as(); - registeredWithBackgroundTask = true; + registeredTaskFromBuilder = builder.Register(); } - PushNotificationRegistrationToken token = { cookie, registeredTask }; + PushNotificationRegistrationToken token = { cookie, registeredTaskFromBuilder }; scopeExitToCleanRegistrations.release(); return token; } - void PushNotificationManager::UnregisterActivator(PushNotificationRegistrationToken const& token, PushNotificationRegistrationOption const& option) + void PushNotificationManager::UnregisterActivator(PushNotificationRegistrationToken const& token, PushNotificationRegistrationOptions const& options) { THROW_HR_IF_NULL(E_INVALIDARG, token); - if (WI_IsFlagSet(option, PushNotificationRegistrationOption::PushTrigger)) + if (WI_IsFlagSet(options, PushNotificationRegistrationOptions::PushTrigger)) { auto taskRegistration = token.TaskRegistration(); THROW_HR_IF_NULL(HRESULT_FROM_WIN32(ERROR_NOT_FOUND), taskRegistration); taskRegistration.Unregister(true); } - if (WI_IsFlagSet(option, PushNotificationRegistrationOption::ComActivator) && token.Cookie()) + // Check for COM flag, a valid cookie and if there are outstanding locks on the PushNotificationBackgroundTask class factory + if (WI_IsFlagSet(options, PushNotificationRegistrationOptions::ComActivator) && token.Cookie() && winrt::get_module_lock() == 0) { LOG_IF_FAILED(::CoRevokeClassObject(static_cast(token.Cookie()))); } diff --git a/dev/PushNotifications/PushNotificationManager.h b/dev/PushNotifications/PushNotificationManager.h index bfb8062f33..0608314613 100644 --- a/dev/PushNotifications/PushNotificationManager.h +++ b/dev/PushNotifications/PushNotificationManager.h @@ -11,7 +11,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation PushNotificationManager() = delete; static Microsoft::Windows::PushNotifications::PushNotificationRegistrationToken RegisterActivator(Microsoft::Windows::PushNotifications::PushNotificationActivationInfo const& details); - static void UnregisterActivator(Microsoft::Windows::PushNotifications::PushNotificationRegistrationToken const& token, Microsoft::Windows::PushNotifications::PushNotificationRegistrationOption const& option); + static void UnregisterActivator(Microsoft::Windows::PushNotifications::PushNotificationRegistrationToken const& token, Microsoft::Windows::PushNotifications::PushNotificationRegistrationOptions const& options); static winrt::Windows::Foundation::IAsyncOperationWithProgress CreateChannelAsync(const winrt::guid &remoteId); diff --git a/dev/PushNotifications/PushNotificationRegistrationToken.cpp b/dev/PushNotifications/PushNotificationRegistrationToken.cpp index ed6581c0bc..c9bd1e08a1 100644 --- a/dev/PushNotifications/PushNotificationRegistrationToken.cpp +++ b/dev/PushNotifications/PushNotificationRegistrationToken.cpp @@ -9,9 +9,9 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { - PushNotificationRegistrationToken::PushNotificationRegistrationToken(uint64_t const& cookie, winrt::Windows::ApplicationModel::Background::IBackgroundTaskRegistration const& taskRegistration): m_cookie(cookie), m_taskRegistration(taskRegistration) { } + PushNotificationRegistrationToken::PushNotificationRegistrationToken(uint32_t const& cookie, winrt::Windows::ApplicationModel::Background::IBackgroundTaskRegistration const& taskRegistration): m_cookie(cookie), m_taskRegistration(taskRegistration) { } - uint64_t PushNotificationRegistrationToken::Cookie() + uint32_t PushNotificationRegistrationToken::Cookie() { return m_cookie; } diff --git a/dev/PushNotifications/PushNotificationRegistrationToken.h b/dev/PushNotifications/PushNotificationRegistrationToken.h index 571917d374..ba7f4ca982 100644 --- a/dev/PushNotifications/PushNotificationRegistrationToken.h +++ b/dev/PushNotifications/PushNotificationRegistrationToken.h @@ -8,12 +8,12 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { struct PushNotificationRegistrationToken : PushNotificationRegistrationTokenT { - PushNotificationRegistrationToken(uint64_t const& cookie, winrt::Windows::ApplicationModel::Background::IBackgroundTaskRegistration const& taskRegistration); - uint64_t Cookie(); + PushNotificationRegistrationToken(uint32_t const& cookie, winrt::Windows::ApplicationModel::Background::IBackgroundTaskRegistration const& taskRegistration); + uint32_t Cookie(); winrt::Windows::ApplicationModel::Background::IBackgroundTaskRegistration TaskRegistration(); private: - const uint64_t m_cookie; + const uint32_t m_cookie; const winrt::Windows::ApplicationModel::Background::IBackgroundTaskRegistration m_taskRegistration; }; } diff --git a/dev/PushNotifications/PushNotifications.idl b/dev/PushNotifications/PushNotifications.idl index dd286ba4e6..7a172ffeb8 100644 --- a/dev/PushNotifications/PushNotifications.idl +++ b/dev/PushNotifications/PushNotifications.idl @@ -10,18 +10,19 @@ namespace Microsoft.Windows.PushNotifications // The Push payload byte[] Payload { get; }; - // Gets a deferral to run under specific modes like low power mode + // Gets a deferral to allow push notification processing even if the system goes into low power mode. Windows.ApplicationModel.Background.BackgroundTaskDeferral GetDeferral(); // Subscribe to Cancelled event handler to be signalled when resource policies are no longer true like 30s wallclock timer event Windows.ApplicationModel.Background.BackgroundTaskCanceledEventHandler Canceled; - // Set to true to prevent proceeding launch due to Background Activation: false by default + // Indicates if the foreground push notification will be re-posted through background activation. + // Default value is false, which allows re-posting. Boolean Handled; }; [flags] - enum PushNotificationRegistrationOption + enum PushNotificationRegistrationOptions { PushTrigger = 0x1, // Registers a Push Trigger with Background Infrastructure ComActivator = 0x2, // Registers the Project Reunion Background Task component as an InProc COM server @@ -33,12 +34,12 @@ namespace Microsoft.Windows.PushNotifications // Initialize using a RegistrationOption and optionally defined parameters like manifest defined activatorId // 1) If option = PushTrigger is specified, only the Push Trigger will be Registered with Background Infrastructure // 2) If option = ComActivator is specified, the Project Reunion Background Task component will be Registered as an InProc COM server - PushNotificationActivationInfo(PushNotificationRegistrationOption option, Guid taskClsid); + PushNotificationActivationInfo(PushNotificationRegistrationOptions options, Guid taskClsid); // The CLSID associated with the Client COM server that Project Reunion will activate Guid TaskClsid{ get; }; - PushNotificationRegistrationOption Option{ get; }; + PushNotificationRegistrationOptions Options{ get; }; // The conditions under which Push Triggers would execute Windows.ApplicationModel.Background.IBackgroundCondition[] GetConditions(); @@ -106,13 +107,13 @@ namespace Microsoft.Windows.PushNotifications runtimeclass PushNotificationRegistrationToken { PushNotificationRegistrationToken( - UInt64 cookie, + UInt32 cookie, Windows.ApplicationModel.Background.IBackgroundTaskRegistration taskRegistration); // The cookie from CoRegisterClassObject - UInt64 Cookie{ get; }; + UInt32 Cookie{ get; }; - // The Registration token for the Push Trigger + // The registration for the Push Trigger Windows.ApplicationModel.Background.IBackgroundTaskRegistration TaskRegistration { get; }; }; @@ -125,7 +126,7 @@ namespace Microsoft.Windows.PushNotifications // Unregister any activator if present using a token and registrationOption // 1) If option = PushTrigger is specified, the trigger itself will be removed // 2) If option = ComActivator is specified, the Project Reunion Background Task component will no longer act as an InProc COM Server - static void UnregisterActivator(PushNotificationRegistrationToken token, PushNotificationRegistrationOption option); + static void UnregisterActivator(PushNotificationRegistrationToken token, PushNotificationRegistrationOptions options); // Request a Push Channel using an encoded AAD GUID identifier from WNS. static Windows.Foundation.IAsyncOperationWithProgress CreateChannelAsync(Guid remoteId); diff --git a/dev/PushNotifications/externs.h b/dev/PushNotifications/externs.h index 91854e85d9..46e5eb307e 100644 --- a/dev/PushNotifications/externs.h +++ b/dev/PushNotifications/externs.h @@ -5,6 +5,6 @@ #include "pch.h" #include "PushNotificationReceivedEventArgs.h" -extern wil::unique_handle g_waitHandleForArgs; +extern wil::unique_event g_waitHandleForArgs; -const winrt::hstring ACTIVATED_EVENT_ARGS_KEY = L"GlobalActivatedEventArgs"; +inline const winrt::hstring ACTIVATED_EVENT_ARGS_KEY = L"GlobalActivatedEventArgs"; diff --git a/test/TestApps/PushNotificationsDemoApp/main.cpp b/test/TestApps/PushNotificationsDemoApp/main.cpp index 22173e40ee..a53075901a 100644 --- a/test/TestApps/PushNotificationsDemoApp/main.cpp +++ b/test/TestApps/PushNotificationsDemoApp/main.cpp @@ -100,7 +100,7 @@ int main() std::cout << "Project Reunion Push Notification Test App: " << buf << std::endl; PushNotificationActivationInfo info( - PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator, + PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator, winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2")); // same clsid as app manifest auto token = PushNotificationManager::RegisterActivator(info); @@ -139,6 +139,8 @@ int main() std::cin.ignore(); } - PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationOption::ComActivator); // Don't unregister PushTrigger because we still want to receive push notifications from background infrastructure. + // Don't unregister PushTrigger because we still want to receive push notifications from background infrastructure. + PushNotificationManager::UnregisterActivator(token, PushNotificationRegistrationOptions::ComActivator); + return 0; } diff --git a/test/TestApps/PushNotificationsTestApp/main.cpp b/test/TestApps/PushNotificationsTestApp/main.cpp index a7c4809c40..63ba192944 100644 --- a/test/TestApps/PushNotificationsTestApp/main.cpp +++ b/test/TestApps/PushNotificationsTestApp/main.cpp @@ -111,11 +111,12 @@ bool MultipleChannelRequestUsingMultipleRemoteId() bool ActivatorTest() { - PushNotificationManager::UnregisterActivator(std::exchange(appToken, nullptr), PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); + PushNotificationManager::UnregisterActivator(std::exchange(appToken, nullptr), PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator); + try { PushNotificationActivationInfo info( - PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator, + PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator, c_fakeComServerId); fakeToken = PushNotificationManager::RegisterActivator(info); @@ -124,7 +125,7 @@ bool ActivatorTest() return false; } - PushNotificationManager::UnregisterActivator(std::exchange(fakeToken, nullptr), PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); + PushNotificationManager::UnregisterActivator(std::exchange(fakeToken, nullptr), PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator); } catch (...) { @@ -152,7 +153,7 @@ bool RegisterActivatorNullClsid() try { PushNotificationActivationInfo info( - PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator, + PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator, winrt::guid()); // Null guid PushNotificationManager::RegisterActivator(info); } @@ -168,7 +169,7 @@ bool UnregisterActivatorNullToken() winrt::hresult hr = S_OK; try { - PushNotificationManager::UnregisterActivator(nullptr, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); + PushNotificationManager::UnregisterActivator(nullptr, PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator); } catch (...) { @@ -183,7 +184,7 @@ bool UnregisterActivatorNullBackgroundRegistration() try { PushNotificationRegistrationToken badToken{ 0, nullptr }; - PushNotificationManager::UnregisterActivator(badToken, PushNotificationRegistrationOption::PushTrigger); + PushNotificationManager::UnregisterActivator(badToken, PushNotificationRegistrationOptions::PushTrigger); } catch (...) { @@ -198,7 +199,7 @@ bool MultipleRegisterActivatorTest() try { PushNotificationActivationInfo info( - PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator, + PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator, c_fakeComServerId); // Fake clsid to test multiple activators fakeToken = PushNotificationManager::RegisterActivator(info); @@ -251,12 +252,12 @@ void UnregisterClsid() { if (appToken) { - PushNotificationManager::UnregisterActivator(appToken, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); + PushNotificationManager::UnregisterActivator(appToken, PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator); } if (fakeToken) { - PushNotificationManager::UnregisterActivator(fakeToken, PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator); + PushNotificationManager::UnregisterActivator(fakeToken, PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator); } } @@ -269,7 +270,7 @@ int main() try }); PushNotificationActivationInfo info( - PushNotificationRegistrationOption::PushTrigger | PushNotificationRegistrationOption::ComActivator, + PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator, winrt::guid(c_comServerId)); // same clsid as app manifest appToken = PushNotificationManager::RegisterActivator(info); From bd4bc2b03cd3ae7ac06da8ea8de2ab4c68daf069 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Thu, 10 Jun 2021 17:21:56 -0700 Subject: [PATCH 44/53] Refactored unregistering tokens --- .../PushNotificationsTestApp/main.cpp | 72 +++++++++++++------ 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/test/TestApps/PushNotificationsTestApp/main.cpp b/test/TestApps/PushNotificationsTestApp/main.cpp index 63ba192944..d8b98d45e3 100644 --- a/test/TestApps/PushNotificationsTestApp/main.cpp +++ b/test/TestApps/PushNotificationsTestApp/main.cpp @@ -17,8 +17,7 @@ using namespace winrt::Windows::Storage::Streams; winrt::guid remoteId1(L"a2e4a323-b518-4799-9e80-0b37aeb0d225"); // Generated from ms.portal.azure.com winrt::guid remoteId2(L"CA1A4AB2-AC1D-4EFC-A132-E5A191CA285A"); // Dummy guid from visual studio guid tool generator -PushNotificationRegistrationToken appToken = nullptr; -PushNotificationRegistrationToken fakeToken = nullptr; +PushNotificationRegistrationToken g_appToken = nullptr; bool ChannelRequestUsingNullRemoteId() { @@ -60,6 +59,7 @@ bool ChannelRequestUsingRemoteId() return channelOperationResult == S_OK; } +// Verify calling channel close will fail when called twice. bool MultipleChannelClose() { auto channelOperation = PushNotificationManager::CreateChannelAsync(remoteId1); @@ -111,7 +111,7 @@ bool MultipleChannelRequestUsingMultipleRemoteId() bool ActivatorTest() { - PushNotificationManager::UnregisterActivator(std::exchange(appToken, nullptr), PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator); + PushNotificationManager::UnregisterActivator(std::exchange(g_appToken, nullptr), PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator); try { @@ -119,6 +119,14 @@ bool ActivatorTest() PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator, c_fakeComServerId); + PushNotificationRegistrationToken fakeToken = nullptr; + auto scope_exit = wil::scope_exit([&] { + if (fakeToken) + { + PushNotificationManager::UnregisterActivator(fakeToken, PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator); + } + }); + fakeToken = PushNotificationManager::RegisterActivator(info); if (!fakeToken.TaskRegistration()) { @@ -134,11 +142,19 @@ bool ActivatorTest() return true; } +// Verify calling register activator with null PushNotificationActivationInfo is not allowed. bool RegisterActivatorNullDetails() { try { - PushNotificationManager::RegisterActivator(nullptr); + PushNotificationRegistrationToken fakeToken = nullptr; + auto scope_exit = wil::scope_exit([&] { + if (fakeToken) + { + PushNotificationManager::UnregisterActivator(fakeToken, PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator); + } + }); + fakeToken = PushNotificationManager::RegisterActivator(nullptr); } catch (...) { @@ -147,6 +163,7 @@ bool RegisterActivatorNullDetails() return false; } +// Verify calling register activator with null clsid is not allowed. bool RegisterActivatorNullClsid() { winrt::hresult hr = S_OK; @@ -155,7 +172,16 @@ bool RegisterActivatorNullClsid() PushNotificationActivationInfo info( PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator, winrt::guid()); // Null guid - PushNotificationManager::RegisterActivator(info); + + PushNotificationRegistrationToken fakeToken = nullptr; + auto scope_exit = wil::scope_exit([&] { + if (fakeToken) + { + PushNotificationManager::UnregisterActivator(fakeToken, PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator); + } + }); + + fakeToken = PushNotificationManager::RegisterActivator(info); } catch (...) { @@ -164,6 +190,7 @@ bool RegisterActivatorNullClsid() return false; } +// Verify unregistering activator with a null token is not allowed. bool UnregisterActivatorNullToken() { winrt::hresult hr = S_OK; @@ -178,6 +205,8 @@ bool UnregisterActivatorNullToken() return false; } +// Verify unregistering an activator with null background registration is not allowed +// if PushTrigger option is specified. bool UnregisterActivatorNullBackgroundRegistration() { winrt::hresult hr = S_OK; @@ -193,6 +222,7 @@ bool UnregisterActivatorNullBackgroundRegistration() return false; } +// Verify registering multiple activators is not allowed. bool MultipleRegisterActivatorTest() { winrt::hresult hr = S_OK; @@ -202,6 +232,14 @@ bool MultipleRegisterActivatorTest() PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator, c_fakeComServerId); // Fake clsid to test multiple activators + PushNotificationRegistrationToken fakeToken = nullptr; + auto scope_exit = wil::scope_exit([&] { + if (fakeToken) + { + PushNotificationManager::UnregisterActivator(fakeToken, PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator); + } + }); + fakeToken = PushNotificationManager::RegisterActivator(info); } catch (...) @@ -211,7 +249,7 @@ bool MultipleRegisterActivatorTest() return false; } -bool BackgroundActivationTest() // Activating application for background. +bool BackgroundActivationTest() // Activating application for background test. { return true; } @@ -247,33 +285,21 @@ bool runUnitTest(std::string unitTest) return it->second(); } -// Cleanup function for exiting test app. -void UnregisterClsid() -{ - if (appToken) - { - PushNotificationManager::UnregisterActivator(appToken, PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator); - } - - if (fakeToken) - { - PushNotificationManager::UnregisterActivator(fakeToken, PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator); - } - -} - int main() try { bool testResult = false; auto scope_exit = wil::scope_exit([&] { - UnregisterClsid(); + if (g_appToken) + { + PushNotificationManager::UnregisterActivator(g_appToken, PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator); + } }); PushNotificationActivationInfo info( PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator, winrt::guid(c_comServerId)); // same clsid as app manifest - appToken = PushNotificationManager::RegisterActivator(info); + g_appToken = PushNotificationManager::RegisterActivator(info); auto args = AppInstance::GetCurrent().GetActivatedEventArgs(); auto kind = args.Kind(); From fd7ba4a75f4f6909acdb80eff6ce3f3dfb71ed4b Mon Sep 17 00:00:00 2001 From: Daniel Ayala Date: Fri, 11 Jun 2021 17:28:34 -0700 Subject: [PATCH 45/53] Addressed last comments --- dev/PushNotifications/PushNotificationChannel.cpp | 2 +- dev/PushNotifications/PushNotificationChannel.h | 2 +- dev/PushNotifications/PushNotificationManager.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/PushNotifications/PushNotificationChannel.cpp b/dev/PushNotifications/PushNotificationChannel.cpp index 990f362c98..e3d8ed743f 100644 --- a/dev/PushNotifications/PushNotificationChannel.cpp +++ b/dev/PushNotifications/PushNotificationChannel.cpp @@ -46,7 +46,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } } - winrt::event_token PushNotificationChannel::PushReceived(winrt::Windows::TypedEventHandler const& handler) + winrt::event_token PushNotificationChannel::PushReceived(winrt::Windows::TypedEventHandler handler) { return m_channel.PushNotificationReceived([weak_self = get_weak(), handler](auto&&, auto&& args) { diff --git a/dev/PushNotifications/PushNotificationChannel.h b/dev/PushNotifications/PushNotificationChannel.h index 83a4887798..8349d8f6b8 100644 --- a/dev/PushNotifications/PushNotificationChannel.h +++ b/dev/PushNotifications/PushNotificationChannel.h @@ -13,7 +13,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation winrt::Windows::Foundation::DateTime ExpirationTime(); void Close(); - winrt::event_token PushReceived(winrt::Windows::Foundation::TypedEventHandler const& handler); + winrt::event_token PushReceived(winrt::Windows::Foundation::TypedEventHandler handler); void PushReceived(winrt::event_token const& token) noexcept; private: diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp index c655b554c0..8e8c74ab60 100644 --- a/dev/PushNotifications/PushNotificationManager.cpp +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -180,7 +180,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation if (!isTaskRegistered) { builder = BackgroundTaskBuilder(); - builder.Name(backgroundTaskName + taskClsidStr); + builder.Name(backgroundTaskFullName); PushNotificationTrigger trigger{}; builder.SetTrigger(trigger); From a030fe5c5d4c38263798226e65f247dffd272d66 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Wed, 16 Jun 2021 09:58:52 -0700 Subject: [PATCH 46/53] Add .Windows to Application model --- .../ProjectReunion-CreateNugetPackage-Job.yml | 2 +- build/CopyFilesToStagingDir.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/AzurePipelinesTemplates/ProjectReunion-CreateNugetPackage-Job.yml b/build/AzurePipelinesTemplates/ProjectReunion-CreateNugetPackage-Job.yml index 18b9ae8ab7..54fe02febf 100644 --- a/build/AzurePipelinesTemplates/ProjectReunion-CreateNugetPackage-Job.yml +++ b/build/AzurePipelinesTemplates/ProjectReunion-CreateNugetPackage-Job.yml @@ -62,7 +62,7 @@ jobs: Copy-Item -Path "$targetsFilePath\AppxManifest.xml" -Destination "$fullpackagePath\AppxManifest.xml" Copy-Item -Path "$targetsFilePath\Intellisense\Microsoft.Windows.AppLifecycle.xml" -Destination "$fullpackagePath\lib\uap10.0\Microsoft.Windows.AppLifecycle.xml" - Copy-Item -Path "$targetsFilePath\Intellisense\Microsoft.ApplicationModel.DynamicDependency.xml" -Destination "$fullpackagePath\lib\uap10.0\Microsoft.ApplicationModel.DynamicDependency.xml" + Copy-Item -Path "$targetsFilePath\Intellisense\Microsoft.Windows.ApplicationModel.DynamicDependency.xml" -Destination "$fullpackagePath\lib\uap10.0\Microsoft.Windows.ApplicationModel.DynamicDependency.xml" Copy-Item -Path "$targetsFilePath\Intellisense\Microsoft.Windows.PushNotifications.xml" -Destination "$fullpackagePath\lib\uap10.0\Microsoft.Windows.PushNotifications.xml" # - script: | diff --git a/build/CopyFilesToStagingDir.ps1 b/build/CopyFilesToStagingDir.ps1 index 758d489b32..8375551935 100644 --- a/build/CopyFilesToStagingDir.ps1 +++ b/build/CopyFilesToStagingDir.ps1 @@ -39,7 +39,7 @@ PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.ProjectReunion.dll $Fu PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.ProjectReunion.lib $FullPublishDir\Microsoft.ProjectReunion\ PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.Windows.AppLifecycle.winmd $FullPublishDir\Microsoft.ProjectReunion\ PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.Windows.PushNotifications.winmd $FullPublishDir\Microsoft.ProjectReunion\ -PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.ApplicationModel.DynamicDependency.winmd $FullPublishDir\Microsoft.ProjectReunion\ +PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.Windows.ApplicationModel.DynamicDependency.winmd $FullPublishDir\Microsoft.ProjectReunion\ PublishFile $FullBuildOutput\ProjectReunion_DLL\MsixDynamicDependency.h $FullPublishDir\Microsoft.ProjectReunion\ PublishFile $FullBuildOutput\ProjectReunion_DLL\wil_msixdynamicdependency.h $FullPublishDir\Microsoft.ProjectReunion\ # From c20a9ecf5e8d6dbae51a25b0e1869dfeb872b601 Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Thu, 17 Jun 2021 11:02:04 -0700 Subject: [PATCH 47/53] Fixed unit test nits --- test/PushNotificationTests/APITests.cpp | 43 +++++++++++++------------ test/PushNotificationTests/pch.h | 3 +- test/inc/ProjectReunion.Test.TAEF.h | 17 ++++++++++ test/inc/TestDef.h | 2 -- test/inc/inc.vcxitems | 1 + 5 files changed, 43 insertions(+), 23 deletions(-) create mode 100644 test/inc/ProjectReunion.Test.TAEF.h diff --git a/test/PushNotificationTests/APITests.cpp b/test/PushNotificationTests/APITests.cpp index 13f35ff04c..6ce3165e7c 100644 --- a/test/PushNotificationTests/APITests.cpp +++ b/test/PushNotificationTests/APITests.cpp @@ -33,11 +33,14 @@ namespace Test::PushNotifications TEST_CLASS_PROPERTY(L"RunAs:Class", L"RestrictedUser") END_TEST_CLASS() - static std::filesystem::path GetDeploymentDir() + static const int testWaitTime() { - WEX::Common::String testDeploymentDir; - WEX::TestExecution::RuntimeParameters::TryGetValue(L"TestDeploymentDir", testDeploymentDir); - return reinterpret_cast(testDeploymentDir.GetBuffer()); + return 3000; + } + + static const int channelTestWaitTime() + { + return 303000; // Need to wait 300000ms for channel request + 3000ms for application overhead } static PCWSTR GetTestPackageFile() @@ -55,7 +58,7 @@ namespace Test::PushNotifications try { TP::AddPackage_ProjectReunionFramework(); // Installs PRfwk - TP::WapProj::AddPackage(GetDeploymentDir(), GetTestPackageFile(), L".msix"); // Installs PushNotificationsTestApp.msix + TP::WapProj::AddPackage(TAEF::GetDeploymentDir(), GetTestPackageFile(), L".msix"); // Installs PushNotificationsTestApp.msix } catch (...) { @@ -96,7 +99,7 @@ namespace Test::PushNotifications void RunTest(const PCWSTR& testName, const int& waitTime) { - DWORD processId; + DWORD processId {}; VERIFY_SUCCEEDED(m_testAppLauncher->ActivateApplication(L"PushNotificationsTestAppPackage_8wekyb3d8bbwe!App", testName, AO_NONE, &processId)); m_processHandle.reset(OpenProcess(SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processId)); @@ -104,14 +107,14 @@ namespace Test::PushNotifications VERIFY_IS_TRUE(wil::handle_wait(m_processHandle.get(), waitTime)); - DWORD exitCode; + DWORD exitCode {}; VERIFY_WIN32_BOOL_SUCCEEDED(GetExitCodeProcess(m_processHandle.get(), &exitCode)); VERIFY_ARE_EQUAL(exitCode, 0); } TEST_METHOD(BackgroundActivation) { - RunTest(L"BackgroundActivationTest", c_pushTestWait); // Need to launch one time to enable background activation. + RunTest(L"BackgroundActivationTest", testWaitTime()); // Need to launch one time to enable background activation. auto LocalBackgroundTask = winrt::create_instance(c_comServerId, CLSCTX_ALL); auto mockBackgroundTaskInstance = winrt::make(); @@ -120,7 +123,7 @@ namespace Test::PushNotifications TEST_METHOD(MultipleBackgroundActivation) { - RunTest(L"BackgroundActivationTest", c_pushTestWait); // Need to launch one time to enable background activation. + RunTest(L"BackgroundActivationTest", testWaitTime()); // Need to launch one time to enable background activation. auto LocalBackgroundTask1 = winrt::create_instance(c_comServerId, CLSCTX_ALL); auto mockBackgroundTaskInstance1 = winrt::make(); @@ -135,57 +138,57 @@ namespace Test::PushNotifications TEST_METHOD(ChannelRequestUsingNullRemoteId) { - RunTest(L"ChannelRequestUsingNullRemoteId", c_pushTestWait); + RunTest(L"ChannelRequestUsingNullRemoteId", testWaitTime()); } TEST_METHOD(ChannelRequestUsingRemoteId) { - RunTest(L"ChannelRequestUsingRemoteId", c_pushTestChannelWait); + RunTest(L"ChannelRequestUsingRemoteId", channelTestWaitTime()); } TEST_METHOD(MultipleChannelClose) { - RunTest(L"MultipleChannelClose", c_pushTestChannelWait); + RunTest(L"MultipleChannelClose", channelTestWaitTime()); } TEST_METHOD(MultipleChannelRequestUsingSameRemoteId) { - RunTest(L"MultipleChannelRequestUsingSameRemoteId", c_pushTestChannelWait); + RunTest(L"MultipleChannelRequestUsingSameRemoteId", channelTestWaitTime()); } TEST_METHOD(MultipleChannelRequestUsingMultipleRemoteId) { - RunTest(L"MultipleChannelRequestUsingMultipleRemoteId", c_pushTestChannelWait); + RunTest(L"MultipleChannelRequestUsingMultipleRemoteId", channelTestWaitTime()); } TEST_METHOD(ActivatorTest) { - RunTest(L"ActivatorTest", c_pushTestWait); + RunTest(L"ActivatorTest", testWaitTime()); } TEST_METHOD(RegisterActivatorNullDetails) { - RunTest(L"RegisterActivatorNullDetails", c_pushTestWait); + RunTest(L"RegisterActivatorNullDetails", testWaitTime()); } TEST_METHOD(RegisterActivatorNullClsid) { - RunTest(L"RegisterActivatorNullClsid", c_pushTestWait); + RunTest(L"RegisterActivatorNullClsid", testWaitTime()); } TEST_METHOD(UnregisterActivatorNullToken) { - RunTest(L"UnregisterActivatorNullToken", c_pushTestWait); + RunTest(L"UnregisterActivatorNullToken", testWaitTime()); } TEST_METHOD(UnregisterActivatorNullBackgroundRegistration) { - RunTest(L"UnregisterActivatorNullBackgroundRegistration", c_pushTestWait); + RunTest(L"UnregisterActivatorNullBackgroundRegistration", testWaitTime()); } TEST_METHOD(MultipleRegisterActivatorTest) { - RunTest(L"MultipleRegisterActivatorTest", c_pushTestWait); + RunTest(L"MultipleRegisterActivatorTest", testWaitTime()); } }; diff --git a/test/PushNotificationTests/pch.h b/test/PushNotificationTests/pch.h index bdfe7c4dac..68bc0fbf0c 100644 --- a/test/PushNotificationTests/pch.h +++ b/test/PushNotificationTests/pch.h @@ -31,10 +31,11 @@ #include #include #include +#include #include #include #include namespace TP = ::Test::Packages; - +namespace TAEF = ::Test::TAEF; #endif //PCH_H diff --git a/test/inc/ProjectReunion.Test.TAEF.h b/test/inc/ProjectReunion.Test.TAEF.h new file mode 100644 index 0000000000..b56caf0c63 --- /dev/null +++ b/test/inc/ProjectReunion.Test.TAEF.h @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +#ifndef __PROJECTREUNION_TEST_TAEF_H +#define __PROJECTREUNION_TEST_TAEF_H + +namespace Test::TAEF +{ + inline std::filesystem::path GetDeploymentDir() + { + WEX::Common::String testDeploymentDir; + WEX::TestExecution::RuntimeParameters::TryGetValue(L"TestDeploymentDir", testDeploymentDir); + return static_cast(testDeploymentDir); + } +} + +#endif // __PROJECTREUNION_TEST_TAEF_H diff --git a/test/inc/TestDef.h b/test/inc/TestDef.h index 8143274f4e..a95be424d6 100644 --- a/test/inc/TestDef.h +++ b/test/inc/TestDef.h @@ -20,8 +20,6 @@ static const std::wstring c_testInstanceRedirectedPhaseEventName = L"ReunionTest inline const winrt::hstring c_rawNotificationPayload = L""; inline IID c_comServerId = winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2"); // Value from PushNotificationsTestAppPackage ComActivator in appxmanifest. inline IID c_fakeComServerId = winrt::guid("00000000-0000-0000-0000-000000000001"); -inline const int c_pushTestWait = 3000; -inline const int c_pushTestChannelWait = c_pushTestWait + 300000; // Need to wait 300000ms for channel request + 3000ms for application overhead #ifndef WIDEN2 #define WIDEN2(x) L ## x diff --git a/test/inc/inc.vcxitems b/test/inc/inc.vcxitems index eb5a7a9b6e..c15064bccd 100644 --- a/test/inc/inc.vcxitems +++ b/test/inc/inc.vcxitems @@ -20,6 +20,7 @@ + \ No newline at end of file From f09bce5af48545b12922202474c99f1b7f61def3 Mon Sep 17 00:00:00 2001 From: Sharath Manchala <10109130+sharath2727@users.noreply.github.com> Date: Thu, 17 Jun 2021 12:52:28 -0700 Subject: [PATCH 48/53] fix nits --- .../PushNotificationManager.cpp | 32 +++---------------- dev/PushNotifications/PushNotifications.idl | 2 ++ .../PushNotificationsDemoApp/main.cpp | 22 ++++--------- .../Package.appxmanifest | 5 ++- .../PushNotificationsTestApp/main.cpp | 6 ++-- .../Package.appxmanifest | 3 +- 6 files changed, 20 insertions(+), 50 deletions(-) diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp index 8e8c74ab60..16538ce823 100644 --- a/dev/PushNotifications/PushNotificationManager.cpp +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -35,9 +35,9 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation inline constexpr auto c_initialBackoff{ 60s }; inline constexpr auto c_backoffIncrement{ 60s }; - const HRESULT WNP_E_NOT_CONNECTED = (HRESULT)0x880403E8L; - const HRESULT WNP_E_RECONNECTING = (HRESULT)0x880403E9L; - const HRESULT WNP_E_BIND_USER_BUSY = (HRESULT)0x880403FEL; + const HRESULT WNP_E_NOT_CONNECTED = static_cast(0x880403E8L); + const HRESULT WNP_E_RECONNECTING = static_cast(0x880403E9L); + const HRESULT WNP_E_BIND_USER_BUSY = static_cast(0x880403FEL); bool PushNotificationManager::IsChannelRequestRetryable(const hresult& hr) { @@ -55,30 +55,12 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation } } - inline bool IsPackagedProcess() - { - wchar_t packageFullName[PACKAGE_FULL_NAME_MAX_LENGTH + 1] = {}; - - UINT32 packageFullNameLength = static_cast(ARRAYSIZE(packageFullName)); - - const auto packagedProcessError = ::GetCurrentPackageFullName(&packageFullNameLength, packageFullName); - - if (packagedProcessError == APPMODEL_ERROR_NO_PACKAGE) - { - return false; - } - - THROW_IF_WIN32_ERROR(packagedProcessError); - - return true; - } - winrt::IAsyncOperationWithProgress PushNotificationManager::CreateChannelAsync(const winrt::guid &remoteId) { THROW_HR_IF(E_INVALIDARG, (remoteId == winrt::guid())); // API supports channel requests only for packaged applications for v0.8 version - THROW_HR_IF(E_NOTIMPL, !IsPackagedProcess()); + THROW_HR_IF(E_NOTIMPL, !AppModel::Identity::IsPackagedProcess()); auto cancellation{ co_await winrt::get_cancellation_token() }; @@ -185,10 +167,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation PushNotificationTrigger trigger{}; builder.SetTrigger(trigger); - if (!IsPackagedProcess()) - { - throw winrt::hresult_not_implemented(); - } + THROW_HR_IF(E_NOTIMPL, !AppModel::Identity::IsPackagedProcess()); // In case the interface is not supported, let it throw. auto builder5 = builder.as(); @@ -216,7 +195,6 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation { registeredTask.Unregister(true); } - } ); diff --git a/dev/PushNotifications/PushNotifications.idl b/dev/PushNotifications/PushNotifications.idl index 7a172ffeb8..eb98a22671 100644 --- a/dev/PushNotifications/PushNotifications.idl +++ b/dev/PushNotifications/PushNotifications.idl @@ -46,6 +46,7 @@ namespace Microsoft.Windows.PushNotifications void SetConditions(Windows.ApplicationModel.Background.IBackgroundCondition[] conditions); }; + [experimental] enum PushNotificationChannelStatus { InProgress, // The request is in progress and there is no retry operation @@ -55,6 +56,7 @@ namespace Microsoft.Windows.PushNotifications }; // The PushNotificationChannel Progress result + [experimental] struct PushNotificationCreateChannelStatus { // Either InProgress or InProgressRetry status diff --git a/test/TestApps/PushNotificationsDemoApp/main.cpp b/test/TestApps/PushNotificationsDemoApp/main.cpp index a53075901a..f01f6ca889 100644 --- a/test/TestApps/PushNotificationsDemoApp/main.cpp +++ b/test/TestApps/PushNotificationsDemoApp/main.cpp @@ -3,10 +3,7 @@ #include "pch.h" #include #include -#include -#include // we need this for BackgroundTask APIs - -#define SIZE 26 +#include using namespace winrt::Microsoft::Windows::AppLifecycle; using namespace winrt::Microsoft::Windows::PushNotifications; @@ -92,13 +89,6 @@ winrt::Microsoft::Windows::PushNotifications::PushNotificationChannel RequestCha int main() { - time_t ltime; - char buf[SIZE]; - - time(<ime); - ctime_s(buf, sizeof buf, <ime); - std::cout << "Project Reunion Push Notification Test App: " << buf << std::endl; - PushNotificationActivationInfo info( PushNotificationRegistrationOptions::PushTrigger | PushNotificationRegistrationOptions::ComActivator, winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2")); // same clsid as app manifest @@ -118,8 +108,8 @@ int main() // Do stuff to process the raw payload std::string payloadString(payload.begin(), payload.end()); - std::cout << "Push notification content received from BACKGROUND: " << payloadString << std::endl << std::endl; - std::cout << "Press 'Enter' to exit the App." << std::endl; + printf("Push notification content received from BACKGROUND: %ws\n", payloadString); + printf("Press 'Enter' to exit the App."); // Call Complete on the deferral when finished processing the payload. // This removes the override that kept the app running even when the system was in a low power mode. @@ -129,13 +119,13 @@ int main() else if (kind == ExtendedActivationKind::Launch) { PushNotificationChannel channel = RequestChannel(); - std::cout << "Press 'Enter' at any time to exit App." << std::endl << std::endl; + printf("Press 'Enter' at any time to exit App."); std::cin.ignore(); } else if (kind == ExtendedActivationKind::ToastNotification) { - std::cout << "ToastNotification received!" << std::endl << std::endl; - std::cout << "Press 'Enter' at any time to exit App." << std::endl << std::endl; + printf("ToastNotification received!"); + printf("Press 'Enter' at any time to exit App."); std::cin.ignore(); } diff --git a/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest b/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest index ca577e6345..01d6475c53 100644 --- a/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest +++ b/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest @@ -19,9 +19,8 @@ - - - + + diff --git a/test/TestApps/PushNotificationsTestApp/main.cpp b/test/TestApps/PushNotificationsTestApp/main.cpp index d8b98d45e3..d0c85e9ebb 100644 --- a/test/TestApps/PushNotificationsTestApp/main.cpp +++ b/test/TestApps/PushNotificationsTestApp/main.cpp @@ -19,6 +19,8 @@ winrt::guid remoteId2(L"CA1A4AB2-AC1D-4EFC-A132-E5A191CA285A"); // Dummy guid fr PushNotificationRegistrationToken g_appToken = nullptr; +constexpr auto timeout{ std::chrono::seconds(300) }; + bool ChannelRequestUsingNullRemoteId() { try @@ -34,7 +36,7 @@ bool ChannelRequestUsingNullRemoteId() HRESULT ChannelRequestHelper(IAsyncOperationWithProgress const& channelOperation) { - if (channelOperation.wait_for(std::chrono::seconds(300)) != AsyncStatus::Completed) + if (channelOperation.wait_for(timeout) != AsyncStatus::Completed) { channelOperation.Cancel(); return HRESULT_FROM_WIN32(ERROR_TIMEOUT); // timed out or failed @@ -63,7 +65,7 @@ bool ChannelRequestUsingRemoteId() bool MultipleChannelClose() { auto channelOperation = PushNotificationManager::CreateChannelAsync(remoteId1); - if (channelOperation.wait_for(std::chrono::seconds(300)) != AsyncStatus::Completed) + if (channelOperation.wait_for(timeout) != AsyncStatus::Completed) { channelOperation.Cancel(); return false; // timed out or failed diff --git a/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest b/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest index c5fa3fbd34..fcf6313839 100644 --- a/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest +++ b/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest @@ -19,8 +19,7 @@ - - + From 3170c37522cb3e4f20c90b83178f0b716382783d Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Thu, 17 Jun 2021 14:39:49 -0700 Subject: [PATCH 49/53] Fixed appmanifests and nits --- build/CopyFilesToStagingDir.ps1 | 1 - .../GetRawNotificationEventArgs.h | 3 +- .../PushNotificationBackgroundTask.h | 4 +- .../PushNotificationManager.cpp | 4 +- .../Package.appxmanifest | 5 ++- .../PushNotificationsDemoPackage.wapproj | 37 +++---------------- .../Package.appxmanifest | 5 ++- .../PushNotificationsTestAppPackage.wapproj | 28 -------------- 8 files changed, 17 insertions(+), 70 deletions(-) diff --git a/build/CopyFilesToStagingDir.ps1 b/build/CopyFilesToStagingDir.ps1 index 8375551935..9d6f5bf459 100644 --- a/build/CopyFilesToStagingDir.ps1 +++ b/build/CopyFilesToStagingDir.ps1 @@ -123,7 +123,6 @@ PublishFile $FullBuildOutput\ProjectReunion_BootstrapDLL\Microsoft.ProjectReunio PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.Windows.AppLifecycle.winmd $NugetDir\lib\native PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.Windows.ApplicationModel.DynamicDependency.winmd $NugetDir\lib\native PublishFile $FullBuildOutput\ProjectReunion_DLL\Microsoft.Windows.PushNotifications.winmd $NugetDir\lib\native - # # C#/WinRT Projections # diff --git a/dev/PushNotifications/GetRawNotificationEventArgs.h b/dev/PushNotifications/GetRawNotificationEventArgs.h index 58d4518b18..fdef3bfbea 100644 --- a/dev/PushNotifications/GetRawNotificationEventArgs.h +++ b/dev/PushNotifications/GetRawNotificationEventArgs.h @@ -12,7 +12,8 @@ namespace winrt::Microsoft::Windows::PushNotifications { static winrt::Windows::Foundation::IInspectable Deserialize(winrt::Windows::Foundation::Uri const&) { - THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_TIMEOUT), !g_waitHandleForArgs.wait(2000)); + const DWORD receiveArgsTimeoutInMSec{ 2000 }; + THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_TIMEOUT), !g_waitHandleForArgs.wait(receiveArgsTimeoutInMSec)); return winrt::Windows::ApplicationModel::Core::CoreApplication::Properties().TryLookup(ACTIVATED_EVENT_ARGS_KEY).as(); } } diff --git a/dev/PushNotifications/PushNotificationBackgroundTask.h b/dev/PushNotifications/PushNotificationBackgroundTask.h index fc8b59ad9b..fb285a67d7 100644 --- a/dev/PushNotifications/PushNotificationBackgroundTask.h +++ b/dev/PushNotifications/PushNotificationBackgroundTask.h @@ -18,14 +18,14 @@ struct PushNotificationBackgroundTask : winrt::implements { - HRESULT __stdcall CreateInstance(_In_opt_ IUnknown* aggregateInterface, _In_ REFIID interfaceId, _Outptr_ VOID** object) noexcept final try + STDMETHODIMP CreateInstance(_In_opt_ IUnknown* aggregateInterface, _In_ REFIID interfaceId, _Outptr_ VOID** object) noexcept final try { RETURN_HR_IF(CLASS_E_NOAGGREGATION, aggregateInterface != nullptr); return winrt::make().as(interfaceId, object); } CATCH_RETURN() - HRESULT __stdcall LockServer(BOOL fLock) noexcept final + STDMETHODIMP LockServer(BOOL fLock) noexcept final { if (fLock) { diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp index 16538ce823..5edbba6e56 100644 --- a/dev/PushNotifications/PushNotificationManager.cpp +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -35,7 +35,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation inline constexpr auto c_initialBackoff{ 60s }; inline constexpr auto c_backoffIncrement{ 60s }; - const HRESULT WNP_E_NOT_CONNECTED = static_cast(0x880403E8L); + const HRESULT WNP_E_NOT_CONNECTED{ 0x880403E8L }; const HRESULT WNP_E_RECONNECTING = static_cast(0x880403E9L); const HRESULT WNP_E_BIND_USER_BUSY = static_cast(0x880403FEL); @@ -201,7 +201,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation if (WI_IsFlagSet(registrationOptions, PushNotificationRegistrationOptions::ComActivator)) { g_waitHandleForArgs.create(); - THROW_HR_IF_NULL(E_UNEXPECTED, g_waitHandleForArgs); + THROW_HR_IF_NULL(HRESULT_FROM_WIN32(GetLastError()), g_waitHandleForArgs); THROW_IF_FAILED(::CoRegisterClassObject( taskClsid, diff --git a/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest b/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest index 01d6475c53..eb7cb01b9a 100644 --- a/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest +++ b/test/TestApps/PushNotificationsDemoPackage/Package.appxmanifest @@ -3,9 +3,10 @@ + IgnorableNamespaces="uap uap5 rescap com"> - + diff --git a/test/TestApps/PushNotificationsDemoPackage/PushNotificationsDemoPackage.wapproj b/test/TestApps/PushNotificationsDemoPackage/PushNotificationsDemoPackage.wapproj index ce21dd0476..edaf9dee12 100644 --- a/test/TestApps/PushNotificationsDemoPackage/PushNotificationsDemoPackage.wapproj +++ b/test/TestApps/PushNotificationsDemoPackage/PushNotificationsDemoPackage.wapproj @@ -20,14 +20,6 @@ Release x64 - - Debug - ARM - - - Release - ARM - Debug ARM64 @@ -36,14 +28,6 @@ Release ARM64 - - Debug - AnyCPU - - - Release - AnyCPU - $(MSBuildExtensionsPath)\Microsoft\DesktopBridge\ @@ -65,36 +49,25 @@ $(Platform) 0 - + Always - + Always - + Always Always - - Always - - + Always Always - - Always - - - Always - - - Always - + Designer diff --git a/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest b/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest index fcf6313839..0946f11bdc 100644 --- a/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest +++ b/test/TestApps/PushNotificationsTestAppPackage/Package.appxmanifest @@ -3,9 +3,10 @@ + IgnorableNamespaces="uap uap5 rescap com"> - + diff --git a/test/TestApps/PushNotificationsTestAppPackage/PushNotificationsTestAppPackage.wapproj b/test/TestApps/PushNotificationsTestAppPackage/PushNotificationsTestAppPackage.wapproj index adbec5a233..4e58890cf2 100644 --- a/test/TestApps/PushNotificationsTestAppPackage/PushNotificationsTestAppPackage.wapproj +++ b/test/TestApps/PushNotificationsTestAppPackage/PushNotificationsTestAppPackage.wapproj @@ -20,14 +20,6 @@ Release x64 - - Debug - ARM - - - Release - ARM - Debug ARM64 @@ -36,14 +28,6 @@ Release ARM64 - - Debug - AnyCPU - - - Release - AnyCPU - $(MSBuildExtensionsPath)\Microsoft\DesktopBridge\ @@ -71,30 +55,18 @@ Always - - Always - Always - - Always - Always Always - - Always - Always - - Always - Designer From bcd75e9bb5f8ac1390e92f4c84e5b6394e83d96d Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Thu, 17 Jun 2021 15:46:13 -0700 Subject: [PATCH 50/53] Removed Debug_test/ARM from PR.sln --- ProjectReunion.sln | 78 ------------------- .../PushNotificationManager.cpp | 2 +- .../PushNotificationsDemoApp/main.cpp | 2 +- 3 files changed, 2 insertions(+), 80 deletions(-) diff --git a/ProjectReunion.sln b/ProjectReunion.sln index 1b7ccf9742..178ac03ac4 100644 --- a/ProjectReunion.sln +++ b/ProjectReunion.sln @@ -487,51 +487,21 @@ Global {A3FBA80D-5B35-471F-9A45-DB4B29E195B9}.Release|x86.ActiveCfg = Release|x86 {A3FBA80D-5B35-471F-9A45-DB4B29E195B9}.Release|x86.Build.0 = Release|x86 {A3FBA80D-5B35-471F-9A45-DB4B29E195B9}.Release|x86.Deploy.0 = Release|x86 - {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|Any CPU.ActiveCfg = Debug|Win32 - {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|Any CPU.Build.0 = Debug|Win32 - {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|ARM.ActiveCfg = Debug|Win32 - {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|ARM.Build.0 = Debug|Win32 - {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|ARM64.ActiveCfg = Debug|Win32 - {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|ARM64.Build.0 = Debug|Win32 - {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|x64.ActiveCfg = Debug|x64 - {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|x64.Build.0 = Debug|x64 - {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|x86.ActiveCfg = Debug|Win32 - {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug_test|x86.Build.0 = Debug|Win32 {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|ARM.ActiveCfg = Debug|Win32 {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|ARM64.ActiveCfg = Debug|Win32 {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|x64.ActiveCfg = Debug|x64 {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|x64.Build.0 = Debug|x64 {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|x86.ActiveCfg = Debug|Win32 {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|x86.Build.0 = Debug|Win32 {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|Any CPU.ActiveCfg = Release|Win32 - {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|ARM.ActiveCfg = Release|Win32 {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|ARM64.ActiveCfg = Release|Win32 {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|x64.ActiveCfg = Release|x64 {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|x64.Build.0 = Release|x64 {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|x86.ActiveCfg = Release|Win32 {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|x86.Build.0 = Release|Win32 - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|Any CPU.ActiveCfg = Debug|Any CPU - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|Any CPU.Build.0 = Debug|Any CPU - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|Any CPU.Deploy.0 = Debug|Any CPU - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|ARM.ActiveCfg = Debug|ARM - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|ARM.Build.0 = Debug|ARM - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|ARM.Deploy.0 = Debug|ARM - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|ARM64.Build.0 = Debug|ARM64 - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|ARM64.Deploy.0 = Debug|ARM64 - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|x64.ActiveCfg = Debug|x64 - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|x64.Build.0 = Debug|x64 - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|x64.Deploy.0 = Debug|x64 - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|x86.ActiveCfg = Debug|x86 - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|x86.Build.0 = Debug|x86 - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug_test|x86.Deploy.0 = Debug|x86 {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|Any CPU.Build.0 = Debug|Any CPU {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|ARM.ActiveCfg = Debug|ARM - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|ARM.Build.0 = Debug|ARM - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|ARM.Deploy.0 = Debug|ARM {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|ARM64.ActiveCfg = Debug|ARM64 {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|ARM64.Build.0 = Debug|ARM64 {424A6D96-37EE-4456-8347-08AB425C8DBE}.Debug|ARM64.Deploy.0 = Debug|ARM64 @@ -544,9 +514,6 @@ Global {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|Any CPU.ActiveCfg = Release|Any CPU {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|Any CPU.Build.0 = Release|Any CPU {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|Any CPU.Deploy.0 = Release|Any CPU - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|ARM.ActiveCfg = Release|ARM - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|ARM.Build.0 = Release|ARM - {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|ARM.Deploy.0 = Release|ARM {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|ARM64.ActiveCfg = Release|ARM64 {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|ARM64.Build.0 = Release|ARM64 {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|ARM64.Deploy.0 = Release|ARM64 @@ -556,51 +523,21 @@ Global {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|x86.ActiveCfg = Release|x86 {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|x86.Build.0 = Release|x86 {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|x86.Deploy.0 = Release|x86 - {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|Any CPU.ActiveCfg = Debug|Win32 - {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|Any CPU.Build.0 = Debug|Win32 - {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|ARM.ActiveCfg = Debug|Win32 - {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|ARM.Build.0 = Debug|Win32 - {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|ARM64.ActiveCfg = Debug|Win32 - {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|ARM64.Build.0 = Debug|Win32 - {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|x64.ActiveCfg = Debug|x64 - {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|x64.Build.0 = Debug|x64 - {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|x86.ActiveCfg = Debug|Win32 - {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug_test|x86.Build.0 = Debug|Win32 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|ARM.ActiveCfg = Debug|Win32 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|ARM64.ActiveCfg = Debug|Win32 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|x64.ActiveCfg = Debug|x64 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|x64.Build.0 = Debug|x64 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|x86.ActiveCfg = Debug|Win32 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|x86.Build.0 = Debug|Win32 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|Any CPU.ActiveCfg = Release|Win32 - {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|ARM.ActiveCfg = Release|Win32 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|ARM64.ActiveCfg = Release|Win32 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|x64.ActiveCfg = Release|x64 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|x64.Build.0 = Release|x64 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|x86.ActiveCfg = Release|Win32 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|x86.Build.0 = Release|Win32 - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|Any CPU.ActiveCfg = Debug|Any CPU - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|Any CPU.Build.0 = Debug|Any CPU - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|Any CPU.Deploy.0 = Debug|Any CPU - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|ARM.ActiveCfg = Debug|ARM - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|ARM.Build.0 = Debug|ARM - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|ARM.Deploy.0 = Debug|ARM - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|ARM64.ActiveCfg = Debug|ARM64 - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|ARM64.Build.0 = Debug|ARM64 - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|ARM64.Deploy.0 = Debug|ARM64 - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|x64.ActiveCfg = Debug|x64 - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|x64.Build.0 = Debug|x64 - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|x64.Deploy.0 = Debug|x64 - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|x86.ActiveCfg = Debug|x86 - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|x86.Build.0 = Debug|x86 - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug_test|x86.Deploy.0 = Debug|x86 {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|Any CPU.Build.0 = Debug|Any CPU {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|Any CPU.Deploy.0 = Debug|Any CPU - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|ARM.ActiveCfg = Debug|ARM - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|ARM.Build.0 = Debug|ARM - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|ARM.Deploy.0 = Debug|ARM {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|ARM64.ActiveCfg = Debug|ARM64 {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|ARM64.Build.0 = Debug|ARM64 {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Debug|ARM64.Deploy.0 = Debug|ARM64 @@ -613,9 +550,6 @@ Global {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|Any CPU.ActiveCfg = Release|Any CPU {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|Any CPU.Build.0 = Release|Any CPU {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|Any CPU.Deploy.0 = Release|Any CPU - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|ARM.ActiveCfg = Release|ARM - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|ARM.Build.0 = Release|ARM - {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|ARM.Deploy.0 = Release|ARM {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|ARM64.ActiveCfg = Release|ARM64 {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|ARM64.Build.0 = Release|ARM64 {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|ARM64.Deploy.0 = Release|ARM64 @@ -625,25 +559,13 @@ Global {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|x86.ActiveCfg = Release|x86 {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|x86.Build.0 = Release|x86 {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|x86.Deploy.0 = Release|x86 - {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|Any CPU.ActiveCfg = Debug|Win32 - {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|Any CPU.Build.0 = Debug|Win32 - {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|ARM.ActiveCfg = Debug|Win32 - {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|ARM.Build.0 = Debug|Win32 - {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|ARM64.ActiveCfg = Debug|Win32 - {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|ARM64.Build.0 = Debug|Win32 - {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|x64.ActiveCfg = Debug|x64 - {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|x64.Build.0 = Debug|x64 - {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|x86.ActiveCfg = Debug|Win32 - {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug_test|x86.Build.0 = Debug|Win32 {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|ARM.ActiveCfg = Debug|Win32 {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|ARM64.ActiveCfg = Debug|Win32 {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|x64.ActiveCfg = Debug|x64 {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|x64.Build.0 = Debug|x64 {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|x86.ActiveCfg = Debug|Win32 {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|x86.Build.0 = Debug|Win32 {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|Any CPU.ActiveCfg = Release|Win32 - {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|ARM.ActiveCfg = Release|Win32 {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|ARM64.ActiveCfg = Release|Win32 {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|x64.ActiveCfg = Release|x64 {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|x64.Build.0 = Release|x64 diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp index 5edbba6e56..372444a084 100644 --- a/dev/PushNotifications/PushNotificationManager.cpp +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -35,7 +35,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation inline constexpr auto c_initialBackoff{ 60s }; inline constexpr auto c_backoffIncrement{ 60s }; - const HRESULT WNP_E_NOT_CONNECTED{ 0x880403E8L }; + const HRESULT WNP_E_NOT_CONNECTED = static_cast(0x880403E8L); const HRESULT WNP_E_RECONNECTING = static_cast(0x880403E9L); const HRESULT WNP_E_BIND_USER_BUSY = static_cast(0x880403FEL); diff --git a/test/TestApps/PushNotificationsDemoApp/main.cpp b/test/TestApps/PushNotificationsDemoApp/main.cpp index f01f6ca889..599fc29cdb 100644 --- a/test/TestApps/PushNotificationsDemoApp/main.cpp +++ b/test/TestApps/PushNotificationsDemoApp/main.cpp @@ -108,7 +108,7 @@ int main() // Do stuff to process the raw payload std::string payloadString(payload.begin(), payload.end()); - printf("Push notification content received from BACKGROUND: %ws\n", payloadString); + printf("Push notification content received from BACKGROUND: %s\n", payloadString.c_str()); printf("Press 'Enter' to exit the App."); // Call Complete on the deferral when finished processing the payload. From 7594c263b25e2ce7b69836a60053830ad6e66285 Mon Sep 17 00:00:00 2001 From: Daniel Ayala Date: Fri, 18 Jun 2021 10:31:10 -0700 Subject: [PATCH 51/53] Replaced global event with global getter and removed a throw macro --- dev/PushNotifications/GetRawNotificationEventArgs.h | 2 +- .../PushNotificationBackgroundTask.cpp | 4 +--- dev/PushNotifications/PushNotificationManager.cpp | 10 ++++++++-- dev/PushNotifications/externs.h | 3 +-- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/dev/PushNotifications/GetRawNotificationEventArgs.h b/dev/PushNotifications/GetRawNotificationEventArgs.h index fdef3bfbea..2279040ac2 100644 --- a/dev/PushNotifications/GetRawNotificationEventArgs.h +++ b/dev/PushNotifications/GetRawNotificationEventArgs.h @@ -13,7 +13,7 @@ namespace winrt::Microsoft::Windows::PushNotifications static winrt::Windows::Foundation::IInspectable Deserialize(winrt::Windows::Foundation::Uri const&) { const DWORD receiveArgsTimeoutInMSec{ 2000 }; - THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_TIMEOUT), !g_waitHandleForArgs.wait(receiveArgsTimeoutInMSec)); + THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_TIMEOUT), !GetWaitHandleForArgs().wait(receiveArgsTimeoutInMSec)); return winrt::Windows::ApplicationModel::Core::CoreApplication::Properties().TryLookup(ACTIVATED_EVENT_ARGS_KEY).as(); } } diff --git a/dev/PushNotifications/PushNotificationBackgroundTask.cpp b/dev/PushNotifications/PushNotificationBackgroundTask.cpp index 632d24cf98..0064416ede 100644 --- a/dev/PushNotifications/PushNotificationBackgroundTask.cpp +++ b/dev/PushNotifications/PushNotificationBackgroundTask.cpp @@ -20,13 +20,11 @@ namespace winrt using namespace Windows::ApplicationModel::Core; } -wil::unique_event g_waitHandleForArgs; - 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); - SetEvent(g_waitHandleForArgs.get()); + SetEvent(GetWaitHandleForArgs().get()); } diff --git a/dev/PushNotifications/PushNotificationManager.cpp b/dev/PushNotifications/PushNotificationManager.cpp index 372444a084..739e1453be 100644 --- a/dev/PushNotifications/PushNotificationManager.cpp +++ b/dev/PushNotifications/PushNotificationManager.cpp @@ -22,6 +22,13 @@ using namespace std::literals; constexpr std::wstring_view backgroundTaskName = L"PushBackgroundTaskName"sv; +static wil::unique_event g_waitHandleForArgs; + +wil::unique_event& GetWaitHandleForArgs() +{ + return g_waitHandleForArgs; +} + namespace winrt { using namespace Windows::ApplicationModel::Background; @@ -200,8 +207,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation if (WI_IsFlagSet(registrationOptions, PushNotificationRegistrationOptions::ComActivator)) { - g_waitHandleForArgs.create(); - THROW_HR_IF_NULL(HRESULT_FROM_WIN32(GetLastError()), g_waitHandleForArgs); + GetWaitHandleForArgs().create(); THROW_IF_FAILED(::CoRegisterClassObject( taskClsid, diff --git a/dev/PushNotifications/externs.h b/dev/PushNotifications/externs.h index 46e5eb307e..19776f45fb 100644 --- a/dev/PushNotifications/externs.h +++ b/dev/PushNotifications/externs.h @@ -3,8 +3,7 @@ #pragma once #include "pch.h" -#include "PushNotificationReceivedEventArgs.h" -extern wil::unique_event g_waitHandleForArgs; +wil::unique_event& GetWaitHandleForArgs(); inline const winrt::hstring ACTIVATED_EVENT_ARGS_KEY = L"GlobalActivatedEventArgs"; From eba1e945ee0564ae27cb5745e0b95227b797741c Mon Sep 17 00:00:00 2001 From: Paul Purifoy Date: Wed, 23 Jun 2021 16:43:33 -0700 Subject: [PATCH 52/53] Adding ARM64 support --- ProjectReunion.sln | 18 ++- .../PushNotificationTests.vcxproj | 136 ++++++++++++++---- .../PushNotificationsDemoApp.vcxproj | 118 +++++++++++++-- .../PushNotificationsTestApp.vcxproj | 118 +++++++++++++-- 4 files changed, 334 insertions(+), 56 deletions(-) diff --git a/ProjectReunion.sln b/ProjectReunion.sln index 178ac03ac4..51f095d088 100644 --- a/ProjectReunion.sln +++ b/ProjectReunion.sln @@ -488,13 +488,15 @@ Global {A3FBA80D-5B35-471F-9A45-DB4B29E195B9}.Release|x86.Build.0 = Release|x86 {A3FBA80D-5B35-471F-9A45-DB4B29E195B9}.Release|x86.Deploy.0 = Release|x86 {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|ARM64.ActiveCfg = Debug|Win32 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|ARM64.Build.0 = Debug|ARM64 {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|x64.ActiveCfg = Debug|x64 {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|x64.Build.0 = Debug|x64 {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|x86.ActiveCfg = Debug|Win32 {5B2D17FE-C371-417F-860C-3D32397C2404}.Debug|x86.Build.0 = Debug|Win32 {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|Any CPU.ActiveCfg = Release|Win32 - {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|ARM64.ActiveCfg = Release|Win32 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|ARM64.ActiveCfg = Release|ARM64 + {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|ARM64.Build.0 = Release|ARM64 {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|x64.ActiveCfg = Release|x64 {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|x64.Build.0 = Release|x64 {5B2D17FE-C371-417F-860C-3D32397C2404}.Release|x86.ActiveCfg = Release|Win32 @@ -524,13 +526,15 @@ Global {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|x86.Build.0 = Release|x86 {424A6D96-37EE-4456-8347-08AB425C8DBE}.Release|x86.Deploy.0 = Release|x86 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|ARM64.ActiveCfg = Debug|Win32 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|ARM64.Build.0 = Debug|ARM64 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|x64.ActiveCfg = Debug|x64 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|x64.Build.0 = Debug|x64 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|x86.ActiveCfg = Debug|Win32 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Debug|x86.Build.0 = Debug|Win32 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|Any CPU.ActiveCfg = Release|Win32 - {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|ARM64.ActiveCfg = Release|Win32 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|ARM64.ActiveCfg = Release|ARM64 + {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|ARM64.Build.0 = Release|ARM64 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|x64.ActiveCfg = Release|x64 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|x64.Build.0 = Release|x64 {56A1D696-FEDA-4333-BF37-772EBECECB10}.Release|x86.ActiveCfg = Release|Win32 @@ -560,13 +564,15 @@ Global {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|x86.Build.0 = Release|x86 {D012E4BB-F16B-472D-A26D-D449CEFA988E}.Release|x86.Deploy.0 = Release|x86 {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|ARM64.ActiveCfg = Debug|Win32 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|ARM64.Build.0 = Debug|ARM64 {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|x64.ActiveCfg = Debug|x64 {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|x64.Build.0 = Debug|x64 {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|x86.ActiveCfg = Debug|Win32 {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Debug|x86.Build.0 = Debug|Win32 {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|Any CPU.ActiveCfg = Release|Win32 - {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|ARM64.ActiveCfg = Release|Win32 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|ARM64.ActiveCfg = Release|ARM64 + {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|ARM64.Build.0 = Release|ARM64 {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|x64.ActiveCfg = Release|x64 {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|x64.Build.0 = Release|x64 {0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|x86.ActiveCfg = Release|Win32 diff --git a/test/PushNotificationTests/PushNotificationTests.vcxproj b/test/PushNotificationTests/PushNotificationTests.vcxproj index 539787bfaf..614f39ac33 100644 --- a/test/PushNotificationTests/PushNotificationTests.vcxproj +++ b/test/PushNotificationTests/PushNotificationTests.vcxproj @@ -18,6 +18,14 @@ Release x64 + + Debug + ARM64 + + + Release + ARM64 + 16.0 @@ -53,6 +61,21 @@ true Unicode + + DynamicLibrary + true + v142 + Unicode + false + + + DynamicLibrary + false + v142 + true + Unicode + false + @@ -71,6 +94,12 @@ + + + + + + true @@ -84,72 +113,124 @@ false - + + true + + + false + + + Use Level3 + true + true true - WIN32;_DEBUG;PUSHNOTIFICATIONTESTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - Use + %(AdditionalIncludeDirectories);$(OutDir)\..\ProjectReunion_DLL;..\inc;$(OutDir)\..\ProjectReunion_BootstrapDLL + WIN32;NDEBUG;%(PreprocessorDefinitions);;INLINE_TEST_METHOD_MARKUP + true pch.h Windows - true - false + true + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);$(OutDir)\..\ProjectReunion_DLL + onecore.lib;onecoreuap.lib;Microsoft.ProjectReunion.lib;wex.common.lib;wex.logger.lib;te.common.lib;%(AdditionalDependencies) + Microsoft.ProjectReunion.Bootstrap.dll;%(DelayLoadDLLs) - + + Use Level3 - true - true true - WIN32;NDEBUG;PUSHNOTIFICATIONTESTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - Use + %(AdditionalIncludeDirectories);$(OutDir)\..\ProjectReunion_DLL;..\inc;$(OutDir)\..\ProjectReunion_BootstrapDLL + WIN32;_DEBUG;%(PreprocessorDefinitions);;INLINE_TEST_METHOD_MARKUP + true pch.h Windows - true - true - true - false + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);$(OutDir)\..\ProjectReunion_DLL + onecore.lib;onecoreuap.lib;Microsoft.ProjectReunion.lib;wex.common.lib;wex.logger.lib;te.common.lib;%(AdditionalDependencies) + Microsoft.ProjectReunion.Bootstrap.dll;%(DelayLoadDLLs) + Use Level3 true - _DEBUG;PUSHNOTIFICATIONTESTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true + %(AdditionalIncludeDirectories);$(OutDir)\..\ProjectReunion_DLL;..\inc;$(OutDir)\..\ProjectReunion_BootstrapDLL + _DEBUG;%(PreprocessorDefinitions);;INLINE_TEST_METHOD_MARKUP + true + pch.h + + + Windows + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);$(OutDir)\..\ProjectReunion_DLL + onecore.lib;onecoreuap.lib;Microsoft.ProjectReunion.lib;wex.common.lib;wex.logger.lib;te.common.lib;%(AdditionalDependencies) + Microsoft.ProjectReunion.Bootstrap.dll;%(DelayLoadDLLs) + + + + Use + Level3 + true + %(AdditionalIncludeDirectories);$(OutDir)\..\ProjectReunion_DLL;..\inc;$(OutDir)\..\ProjectReunion_BootstrapDLL + _DEBUG;%(PreprocessorDefinitions);;INLINE_TEST_METHOD_MARKUP + true pch.h Windows - true - false + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);$(OutDir)\..\ProjectReunion_DLL + onecore.lib;onecoreuap.lib;Microsoft.ProjectReunion.lib;wex.common.lib;wex.logger.lib;te.common.lib;%(AdditionalDependencies) + Microsoft.ProjectReunion.Bootstrap.dll;%(DelayLoadDLLs) + Use Level3 true true true - NDEBUG;PUSHNOTIFICATIONTESTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true + %(AdditionalIncludeDirectories);$(OutDir)\..\ProjectReunion_DLL;..\inc;$(OutDir)\..\ProjectReunion_BootstrapDLL + NDEBUG;%(PreprocessorDefinitions);;INLINE_TEST_METHOD_MARKUP + true + pch.h + + + Windows + true + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);$(OutDir)\..\ProjectReunion_DLL + onecore.lib;onecoreuap.lib;Microsoft.ProjectReunion.lib;wex.common.lib;wex.logger.lib;te.common.lib;%(AdditionalDependencies) + Microsoft.ProjectReunion.Bootstrap.dll;%(DelayLoadDLLs) + + + + Use + Level3 + true + true + true + %(AdditionalIncludeDirectories);$(OutDir)\..\ProjectReunion_DLL;..\inc;$(OutDir)\..\ProjectReunion_BootstrapDLL + NDEBUG;%(PreprocessorDefinitions);;INLINE_TEST_METHOD_MARKUP + true pch.h Windows true true - true - false + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);$(OutDir)\..\ProjectReunion_DLL + onecore.lib;onecoreuap.lib;Microsoft.ProjectReunion.lib;wex.common.lib;wex.logger.lib;te.common.lib;%(AdditionalDependencies) + Microsoft.ProjectReunion.Bootstrap.dll;%(DelayLoadDLLs) @@ -166,6 +247,10 @@ Create Create Create + Create + Create + Create + Create @@ -198,4 +283,7 @@ + + + \ No newline at end of file diff --git a/test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj b/test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj index 5cf53ecdd5..5de8d27327 100644 --- a/test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj +++ b/test/TestApps/PushNotificationsDemoApp/PushNotificationsDemoApp.vcxproj @@ -18,6 +18,14 @@ Release x64 + + Debug + ARM64 + + + Release + ARM64 + 16.0 @@ -53,6 +61,21 @@ true Unicode + + Application + true + v142 + Unicode + false + + + Application + false + v142 + true + Unicode + false + @@ -70,6 +93,12 @@ + + + + + + true @@ -83,65 +112,125 @@ false + + true + + + false + + Use Level3 true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true + %(AdditionalIncludeDirectories);$(OutDir)\..\ProjectReunion_DLL;$(OutDir)\..\ProjectReunion_BootstrapDLL;..\..\inc + WIN32;_DEBUG;%(PreprocessorDefinitions) + pch.h + stdcpp17 Console - true + %(AdditionalLibraryDirectories);$(OutDir)\..\ProjectReunion_DLL + onecore.lib;onecoreuap.lib;Microsoft.ProjectReunion.lib;%(AdditionalDependencies) + Use Level3 true true true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true + %(AdditionalIncludeDirectories);$(OutDir)\..\ProjectReunion_DLL;$(OutDir)\..\ProjectReunion_BootstrapDLL;..\..\inc + WIN32;NDEBUG;%(PreprocessorDefinitions) + pch.h + stdcpp17 Console true true - true + %(AdditionalLibraryDirectories);$(OutDir)\..\ProjectReunion_DLL + onecore.lib;onecoreuap.lib;Microsoft.ProjectReunion.lib;%(AdditionalDependencies) + Use Level3 true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true + %(AdditionalIncludeDirectories);$(OutDir)\..\ProjectReunion_DLL;$(OutDir)\..\ProjectReunion_BootstrapDLL;..\..\inc + _DEBUG;%(PreprocessorDefinitions) + pch.h + stdcpp17 Console - true + %(AdditionalLibraryDirectories);$(OutDir)\..\ProjectReunion_DLL + onecore.lib;onecoreuap.lib;Microsoft.ProjectReunion.lib;%(AdditionalDependencies) + Use Level3 true true true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true + %(AdditionalIncludeDirectories);$(OutDir)\..\ProjectReunion_DLL;$(OutDir)\..\ProjectReunion_BootstrapDLL;..\..\inc + NDEBUG;%(PreprocessorDefinitions) + pch.h + stdcpp17 Console true true - true + %(AdditionalLibraryDirectories);$(OutDir)\..\ProjectReunion_DLL + onecore.lib;onecoreuap.lib;Microsoft.ProjectReunion.lib;%(AdditionalDependencies) + + + + + Use + Level3 + true + %(AdditionalIncludeDirectories);$(OutDir)\..\ProjectReunion_DLL;$(OutDir)\..\ProjectReunion_BootstrapDLL;..\..\inc + _DEBUG;%(PreprocessorDefinitions) + pch.h + stdcpp17 + + + Console + %(AdditionalLibraryDirectories);$(OutDir)\..\ProjectReunion_DLL + onecore.lib;onecoreuap.lib;Microsoft.ProjectReunion.lib;%(AdditionalDependencies) + + + + + Use + Level3 + true + true + true + %(AdditionalIncludeDirectories);$(OutDir)\..\ProjectReunion_DLL;$(OutDir)\..\ProjectReunion_BootstrapDLL;..\..\inc + NDEBUG;%(PreprocessorDefinitions) + pch.h + stdcpp17 + + + Console + true + true + %(AdditionalLibraryDirectories);$(OutDir)\..\ProjectReunion_DLL + onecore.lib;onecoreuap.lib;Microsoft.ProjectReunion.lib;%(AdditionalDependencies) - + + Create + @@ -174,4 +263,7 @@ + + + \ No newline at end of file diff --git a/test/TestApps/PushNotificationsTestApp/PushNotificationsTestApp.vcxproj b/test/TestApps/PushNotificationsTestApp/PushNotificationsTestApp.vcxproj index d4601f457f..1d716c19d1 100644 --- a/test/TestApps/PushNotificationsTestApp/PushNotificationsTestApp.vcxproj +++ b/test/TestApps/PushNotificationsTestApp/PushNotificationsTestApp.vcxproj @@ -18,10 +18,20 @@ Release x64 + + Debug + ARM64 + + + Release + ARM64 + - + + Create + @@ -75,6 +85,21 @@ true Unicode + + Application + true + v142 + Unicode + false + + + Application + false + v142 + true + Unicode + false + @@ -93,6 +118,12 @@ + + + + + + true @@ -106,60 +137,118 @@ false + + true + + + false + + Use Level3 true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true + %(AdditionalIncludeDirectories);$(OutDir)\..\ProjectReunion_DLL;$(OutDir)\..\ProjectReunion_BootstrapDLL;..\..\inc + WIN32;_DEBUG;%(PreprocessorDefinitions) + pch.h + stdcpp17 Console - true + %(AdditionalLibraryDirectories);$(OutDir)\..\ProjectReunion_DLL + onecore.lib;onecoreuap.lib;Microsoft.ProjectReunion.lib;%(AdditionalDependencies) + Use Level3 true true true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true + %(AdditionalIncludeDirectories);$(OutDir)\..\ProjectReunion_DLL;$(OutDir)\..\ProjectReunion_BootstrapDLL;..\..\inc + WIN32;NDEBUG;%(PreprocessorDefinitions) + pch.h + stdcpp17 Console true true - true + %(AdditionalLibraryDirectories);$(OutDir)\..\ProjectReunion_DLL + onecore.lib;onecoreuap.lib;Microsoft.ProjectReunion.lib;%(AdditionalDependencies) + Use Level3 true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true + %(AdditionalIncludeDirectories);$(OutDir)\..\ProjectReunion_DLL;$(OutDir)\..\ProjectReunion_BootstrapDLL;..\..\inc + _DEBUG;%(PreprocessorDefinitions) + pch.h + stdcpp17 Console - true + %(AdditionalLibraryDirectories);$(OutDir)\..\ProjectReunion_DLL + onecore.lib;onecoreuap.lib;Microsoft.ProjectReunion.lib;%(AdditionalDependencies) + Use + Level3 + true + true + true + %(AdditionalIncludeDirectories);$(OutDir)\..\ProjectReunion_DLL;$(OutDir)\..\ProjectReunion_BootstrapDLL;..\..\inc + NDEBUG;%(PreprocessorDefinitions) + pch.h + stdcpp17 + + + Console + true + true + %(AdditionalLibraryDirectories);$(OutDir)\..\ProjectReunion_DLL + onecore.lib;onecoreuap.lib;Microsoft.ProjectReunion.lib;%(AdditionalDependencies) + + + + + Use + Level3 + true + %(AdditionalIncludeDirectories);$(OutDir)\..\ProjectReunion_DLL;$(OutDir)\..\ProjectReunion_BootstrapDLL;..\..\inc + _DEBUG;%(PreprocessorDefinitions) + pch.h + stdcpp17 + + + Console + %(AdditionalLibraryDirectories);$(OutDir)\..\ProjectReunion_DLL + onecore.lib;onecoreuap.lib;Microsoft.ProjectReunion.lib;%(AdditionalDependencies) + + + + + Use Level3 true true true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true + %(AdditionalIncludeDirectories);$(OutDir)\..\ProjectReunion_DLL;$(OutDir)\..\ProjectReunion_BootstrapDLL;..\..\inc + NDEBUG;%(PreprocessorDefinitions) + pch.h + stdcpp17 Console true true - true + %(AdditionalLibraryDirectories);$(OutDir)\..\ProjectReunion_DLL + onecore.lib;onecoreuap.lib;Microsoft.ProjectReunion.lib;%(AdditionalDependencies) @@ -175,4 +264,7 @@ + + + \ No newline at end of file From 4ba3dbe61741e3748ada925f699f369672b114ec Mon Sep 17 00:00:00 2001 From: Daniel Ayala Date: Thu, 24 Jun 2021 09:04:26 -0700 Subject: [PATCH 53/53] Fixed build break - Removed unnecessary dependencies in PR.sln --- ProjectReunion.sln | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/ProjectReunion.sln b/ProjectReunion.sln index 51f095d088..0345efc529 100644 --- a/ProjectReunion.sln +++ b/ProjectReunion.sln @@ -134,9 +134,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PushNotificationsDemoApp", EndProjectSection EndProject Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "PushNotificationsDemoPackage", "test\TestApps\PushNotificationsDemoPackage\PushNotificationsDemoPackage.wapproj", "{424A6D96-37EE-4456-8347-08AB425C8DBE}" - ProjectSection(ProjectDependencies) = postProject - {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} = {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} - EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PushNotificationsTestApp", "test\TestApps\PushNotificationsTestApp\PushNotificationsTestApp.vcxproj", "{56A1D696-FEDA-4333-BF37-772EBECECB10}" ProjectSection(ProjectDependencies) = postProject @@ -148,13 +145,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PushNotificationsTestApp", EndProjectSection EndProject Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "PushNotificationsTestAppPackage", "test\TestApps\PushNotificationsTestAppPackage\PushNotificationsTestAppPackage.wapproj", "{D012E4BB-F16B-472D-A26D-D449CEFA988E}" - ProjectSection(ProjectDependencies) = postProject - {B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1} - {A7391725-4EF5-438F-8DE1-645423E46955} = {A7391725-4EF5-438F-8DE1-645423E46955} - {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} = {9C1A6C58-52D6-4514-9120-5C339C5DF4BE} - {F76B776E-86F5-48C5-8FC7-D2795ECC9746} = {F76B776E-86F5-48C5-8FC7-D2795ECC9746} - {B71E818A-882E-456A-87E5-4DE4A6602B99} = {B71E818A-882E-456A-87E5-4DE4A6602B99} - EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PushNotificationTests", "test\PushNotificationTests\PushNotificationTests.vcxproj", "{0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}" ProjectSection(ProjectDependencies) = postProject