Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 59 additions & 9 deletions dev/PushNotifications/PushNotificationChannel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include "externs.h"
#include "PushNotificationTelemetry.h"
#include <TerminalVelocityFeatures-PushNotifications.h>

#include "PushNotificationUtility.h"

namespace winrt::Windows
{
Expand Down Expand Up @@ -89,15 +89,34 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation
{
if (IsPackagedAppScenario())
{
return m_channel.PushNotificationReceived([weak_self = get_weak(), handler](auto&&, auto&& args)
if (m_channel)
{
return m_channel.PushNotificationReceived([weak_self = get_weak(), handler](auto&&, auto&& args)
{
if (auto strong = weak_self.get())
{
auto pushArgs = winrt::make<winrt::Microsoft::Windows::PushNotifications::implementation::PushNotificationReceivedEventArgs>(args);
pushArgs.Handled(true);
handler(*strong, pushArgs);
};
});
}
else
{
if (auto strong = weak_self.get())
// The channelUri is directly obtained when we request Channel from UDK using RemoteId
auto lock = m_lock.lock_exclusive();

if (!m_foregroundHandlerCount)
{
auto pushArgs = winrt::make<winrt::Microsoft::Windows::PushNotifications::implementation::PushNotificationReceivedEventArgs>(args);
pushArgs.Handled(true);
handler(*strong, pushArgs);
};
});
auto appUserModelId = GetAppUserModelId();

THROW_IF_FAILED(PushNotifications_RegisterNotificationSinkForFullTrustApplication(appUserModelId.get(), this));
}

++m_foregroundHandlerCount;

Comment thread
sharath2727 marked this conversation as resolved.
return m_foregroundHandlers.add(handler);
}
}
else
{
Expand All @@ -120,7 +139,24 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation
{
if (IsPackagedAppScenario())
{
m_channel.PushNotificationReceived(token);
if (m_channel)
{
m_channel.PushNotificationReceived(token);
}
else
{
auto lock = m_lock.lock_exclusive();

if (m_foregroundHandlerCount == 1)
{
auto appUserModelId = GetAppUserModelId();

THROW_IF_FAILED(PushNotifications_UnregisterNotificationSinkForFullTrustApplication(appUserModelId.get()));
}

m_foregroundHandlers.remove(token);
--m_foregroundHandlerCount;
}
}
else
{
Expand Down Expand Up @@ -148,6 +184,20 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation
}
CATCH_RETURN()

HRESULT __stdcall PushNotificationChannel::OnRawNotificationReceived(unsigned int payloadLength, _In_ byte* payload, _In_ HSTRING /*correlationVector */) noexcept try
{
BOOL foregroundHandled = true;
THROW_IF_FAILED(InvokeAll(payloadLength, payload, &foregroundHandled));

if (!foregroundHandled)
{
ProtocolLaunchHelper(payloadLength, payload);
}

return S_OK;
}
CATCH_RETURN();

bool PushNotificationChannel::IsBackgroundTaskBuilderAvailable()
{
return winrt::Windows::ApiInformation::IsMethodPresent(L"Windows.ApplicationModel.Background.BackgroundTaskBuilder", L"SetTaskEntryPointClsid");
Expand Down
6 changes: 5 additions & 1 deletion dev/PushNotifications/PushNotificationChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "Microsoft.Windows.PushNotifications.PushNotificationChannel.g.h"
#include <NotificationsLongRunningProcess_h.h>
#include "winrt/Windows.Networking.PushNotifications.h"
#include <frameworkudk/pushnotificationsRT.h>
#include "externs.h"

namespace winrt::Microsoft::Windows::PushNotifications::implementation
Expand All @@ -13,7 +14,7 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation
winrt::Microsoft::Windows::PushNotifications::PushNotificationChannel,
winrt::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs> PushNotificationEventHandler;

struct PushNotificationChannel : PushNotificationChannelT<PushNotificationChannel, IWpnForegroundSink>
struct PushNotificationChannel : PushNotificationChannelT<PushNotificationChannel, IWpnForegroundSink, ABI::Microsoft::Internal::PushNotifications::INotificationListener>
{
PushNotificationChannel(winrt::Windows::Networking::PushNotifications::PushNotificationChannel const& channel);

Expand All @@ -29,6 +30,9 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation
// IWpnForegroundSink
HRESULT __stdcall InvokeAll(_In_ ULONG length, _In_ byte* payload, _Out_ BOOL* foregroundHandled) noexcept;

// INotificationHandler
HRESULT __stdcall OnRawNotificationReceived(unsigned int payloadLength, _In_ byte* payload, _In_ HSTRING /*correlationVector */) noexcept;

private:
bool IsPackagedAppScenario();
bool IsBackgroundTaskBuilderAvailable();
Expand Down
69 changes: 69 additions & 0 deletions dev/PushNotifications/PushNotificationUtility.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// 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 "externs.h"
#include "PushNotificationUtility.h"

wil::unique_cotaskmem_string GetAppUserModelId()
{
wchar_t appId[APPLICATION_USER_MODEL_ID_MAX_LENGTH] = {};
UINT32 appIdSize{ ARRAYSIZE(appId) };

THROW_IF_FAILED(::GetCurrentApplicationUserModelId(&appIdSize, appId));

return wil::make_unique_string<wil::unique_cotaskmem_string>(appId);
}

std::wstring Utf8BytesToWideString(unsigned int payloadLength, _In_reads_(payloadLength) byte* payload)
{
int size = MultiByteToWideChar(
CP_UTF8,
0,
reinterpret_cast<PCSTR>(payload),
payloadLength,
nullptr,
0);
THROW_LAST_ERROR_IF(size == 0);

std::wstring payloadAsWideString(size, 0);
size = MultiByteToWideChar(
CP_UTF8,
0,
reinterpret_cast<PCSTR>(payload),
payloadLength,
&payloadAsWideString[0],
size);
THROW_LAST_ERROR_IF(size == 0);

return payloadAsWideString;
}

void ProtocolLaunchHelper(unsigned int payloadLength, _In_reads_(payloadLength) byte* payload)
{
// Command line format: ----WindowsAppRuntimePushServer:-Payload:"<payloadAsEscapedUriFormat>"
std::wstring commandLine = L"----WindowsAppRuntimePushServer:-Payload:\"";

// Escape special characters to follow command line standards for any app activation type in AppLifecycle
// (See AppInstance.cpp and Serialize() from other activation types)
std::wstring payloadAsWideString = Utf8BytesToWideString(payloadLength, payload);
auto payloadAsEscapedUriFormat = winrt::Windows::Foundation::Uri::EscapeComponent(payloadAsWideString.c_str());

commandLine.append(payloadAsEscapedUriFormat);
commandLine.append(L"\"");

wil::unique_cotaskmem_string processName;
THROW_IF_FAILED(GetCurrentProcessPath(processName));

SHELLEXECUTEINFO shellExecuteInfo{};
shellExecuteInfo.cbSize = sizeof(SHELLEXECUTEINFO);
shellExecuteInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_DOENVSUBST;
shellExecuteInfo.lpFile = processName.get();
shellExecuteInfo.lpParameters = commandLine.c_str();

shellExecuteInfo.nShow = SW_NORMAL;

if (!ShellExecuteEx(&shellExecuteInfo))
{
THROW_IF_WIN32_ERROR(GetLastError());
}
}
9 changes: 9 additions & 0 deletions dev/PushNotifications/PushNotificationUtility.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// 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"

const std::wstring ConvertByteArrayToWideString(unsigned int payloadLength, _In_reads_(payloadLength) byte* payload);
void ProtocolLaunchHelper(unsigned int payloadLength, _In_reads_(payloadLength) byte* payload);
wil::unique_cotaskmem_string GetAppUserModelId();
5 changes: 5 additions & 0 deletions dev/PushNotifications/PushNotifications.vcxitems
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)PushNotificationCreateChannelResult.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)PushNotificationManager.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)PushNotificationReceivedEventArgs.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)PushNotificationUtility.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(MSBuildThisFileDirectory)externs.h" />
Expand All @@ -36,6 +37,10 @@
<ClInclude Include="$(MSBuildThisFileDirectory)PushNotificationRegistrationToken.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)PushNotificationDummyDeferral.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)PushNotificationTelemetry.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)PushNotificationUtility.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)utils.h" />
</ItemGroup>
<ItemGroup>
<PublicHeaders Include="$(MSBuildThisFileDirectory)PushNotificationUtility.h" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)..\WindowsAppSDK_BootstrapDLL</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)\..\WindowsAppRuntime_DLL;$(OutDir)..\WindowsAppSDK_BootstrapDLL</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -141,7 +141,7 @@
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<ControlFlowGuard>Guard</ControlFlowGuard>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)..\WindowsAppSDK_BootstrapDLL</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)\..\WindowsAppRuntime_DLL;$(OutDir)..\WindowsAppSDK_BootstrapDLL</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -158,7 +158,7 @@
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)..\WindowsAppSDK_BootstrapDLL</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)\..\WindowsAppRuntime_DLL;$(OutDir)..\WindowsAppSDK_BootstrapDLL</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -176,7 +176,7 @@
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<ControlFlowGuard>Guard</ControlFlowGuard>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)..\WindowsAppSDK_BootstrapDLL</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)\..\WindowsAppRuntime_DLL;$(OutDir)..\WindowsAppSDK_BootstrapDLL</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -193,7 +193,7 @@
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)..\WindowsAppSDK_BootstrapDLL</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)\..\WindowsAppRuntime_DLL;$(OutDir)..\WindowsAppSDK_BootstrapDLL</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -211,7 +211,7 @@
<ConformanceMode>true</ConformanceMode>
<ControlFlowGuard>Guard</ControlFlowGuard>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)..\WindowsAppSDK_BootstrapDLL</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory);$(OutDir)..\PushNotificationsLongRunningTask.ProxyStub;$(OutDir)\..\WindowsAppRuntime_DLL;$(OutDir)..\WindowsAppSDK_BootstrapDLL</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand Down
1 change: 0 additions & 1 deletion dev/PushNotifications/externs.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,3 @@ inline HRESULT GetCurrentProcessPath(wil::unique_cotaskmem_string& processName)
{
return wil::GetModuleFileNameExW(GetCurrentProcess(), nullptr, processName);
};

2 changes: 1 addition & 1 deletion test/TestApps/PushNotificationsDemoApp/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ winrt::Windows::Foundation::IAsyncOperation<PushNotificationChannel> RequestChan
// To obtain an AAD RemoteIdentifier for your app,
// follow the instructions on https://docs.microsoft.com/azure/active-directory/develop/quickstart-register-app
auto channelOperation = PushNotificationManager::CreateChannelAsync(
winrt::guid("ccd2ae3f-764f-4ae3-be45-9804761b28b2"));
winrt::guid("0160ee84-0c53-4851-9ff2-d7f5a87ed914"));

// Setup the inprogress event handler
channelOperation.Progress(
Expand Down