-
Notifications
You must be signed in to change notification settings - Fork 436
Introducing unpackaged foreground activation for PushNotifications #1336
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
085c2a4
4e3b33b
9e92b46
aa8f821
0869fa5
9628910
383801c
48a68b7
d7e6f18
775a21f
69c7445
f992b5f
24b5bdb
ad2b0d0
2351316
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,16 +2,19 @@ | |
| // Licensed under the MIT License. See LICENSE in the project root for license information. | ||
|
|
||
| #include "pch.h" | ||
| #include <winrt/Windows.Foundation.Metadata.h> | ||
| #include "PushNotificationChannel.h" | ||
| #include "Microsoft.Windows.PushNotifications.PushNotificationChannel.g.cpp" | ||
| #include <winrt\Windows.Networking.PushNotifications.h> | ||
| #include <winrt\Windows.Foundation.h> | ||
| #include "PushNotificationReceivedEventArgs.h" | ||
| #include "externs.h" | ||
|
|
||
| namespace winrt::Windows | ||
| { | ||
| using namespace winrt::Windows::Networking::PushNotifications; | ||
| using namespace winrt::Windows::Foundation; | ||
| using namespace winrt::Windows::Metadata; | ||
| } | ||
| namespace winrt::Microsoft | ||
| { | ||
|
|
@@ -26,10 +29,12 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation | |
| { | ||
| return winrt::Windows::Uri{ m_channel.Uri() }; | ||
| } | ||
|
|
||
| winrt::Windows::DateTime PushNotificationChannel::ExpirationTime() | ||
| { | ||
| return m_channel.ExpirationTime(); | ||
| } | ||
|
|
||
| void PushNotificationChannel::Close() | ||
| { | ||
| try | ||
|
|
@@ -48,18 +53,73 @@ namespace winrt::Microsoft::Windows::PushNotifications::implementation | |
|
|
||
| winrt::event_token PushNotificationChannel::PushReceived(winrt::Windows::TypedEventHandler<winrt::Microsoft::Windows::PushNotifications::PushNotificationChannel, winrt::Microsoft::Windows::PushNotifications::PushNotificationReceivedEventArgs> handler) | ||
| { | ||
| return m_channel.PushNotificationReceived([weak_self = get_weak(), handler](auto&&, auto&& args) | ||
| if (IsPackagedAppScenario()) | ||
| { | ||
| auto strong = weak_self.get(); | ||
| if (strong) | ||
| return m_channel.PushNotificationReceived([weak_self = get_weak(), handler](auto&&, auto&& args) | ||
| { | ||
| handler(*strong, winrt::make<winrt::Microsoft::Windows::PushNotifications::implementation::PushNotificationReceivedEventArgs>(args)); | ||
| }; | ||
| }); | ||
| if (auto strong = weak_self.get()) | ||
| { | ||
| handler(*strong, winrt::make<winrt::Microsoft::Windows::PushNotifications::implementation::PushNotificationReceivedEventArgs>(args)); | ||
| }; | ||
| }); | ||
| } | ||
| else | ||
| { | ||
| auto lock = m_lock.lock_exclusive(); | ||
| if (!m_foregroundHandlerCount++) | ||
| { | ||
| wil::com_ptr<INotificationsLongRunningPlatform> notificationsLongRunningPlatform{ | ||
| wil::CoCreateInstance<NotificationsLongRunningPlatform, INotificationsLongRunningPlatform>(CLSCTX_LOCAL_SERVER) }; | ||
|
|
||
| wil::unique_cotaskmem_string processName; | ||
| THROW_IF_FAILED(GetCurrentProcessPath(processName)); | ||
|
|
||
| THROW_IF_FAILED(notificationsLongRunningPlatform->RegisterForegroundActivator(this, processName.get())); | ||
| } | ||
| return m_foregroundHandlers.add(handler); | ||
| } | ||
| } | ||
|
|
||
| void PushNotificationChannel::PushReceived(winrt::event_token const& token) noexcept | ||
| { | ||
| m_channel.PushNotificationReceived(token); | ||
| if (IsPackagedAppScenario()) | ||
| { | ||
| m_channel.PushNotificationReceived(token); | ||
| } | ||
| else | ||
|
pmpurifoy marked this conversation as resolved.
|
||
| { | ||
| auto lock = m_lock.lock_exclusive(); | ||
| m_foregroundHandlers.remove(token); | ||
| if (!--m_foregroundHandlerCount) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: Don't rely on int to bool conversion as a practise. Always better to say != 0 to be precise. |
||
| { | ||
| wil::com_ptr<INotificationsLongRunningPlatform> notificationsLongRunningPlatform{ | ||
| wil::CoCreateInstance<NotificationsLongRunningPlatform, INotificationsLongRunningPlatform>(CLSCTX_LOCAL_SERVER) }; | ||
|
|
||
| wil::unique_cotaskmem_string processName; | ||
| THROW_IF_FAILED(GetCurrentProcessPath(processName)); | ||
|
|
||
| THROW_IF_FAILED(notificationsLongRunningPlatform->UnregisterForegroundActivator(processName.get())); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| HRESULT __stdcall PushNotificationChannel::InvokeAll(_In_ ULONG length, _In_ byte* payload, _Out_ BOOL* foregroundHandled) noexcept try | ||
| { | ||
| auto args = winrt::make<winrt::Microsoft::Windows::PushNotifications::implementation::PushNotificationReceivedEventArgs>(payload, length); | ||
| m_foregroundHandlers(*this, args); | ||
| *foregroundHandled = args.Handled(); | ||
| return S_OK; | ||
| } | ||
| CATCH_RETURN() | ||
|
|
||
| bool PushNotificationChannel::IsBackgroundTaskBuilderAvailable() | ||
| { | ||
| return winrt::Windows::ApiInformation::IsMethodPresent(L"Windows.ApplicationModel.Background.BackgroundTaskBuilder", L"SetTaskEntryPointClsid"); | ||
| } | ||
|
|
||
| // Determines if the caller should be treated as packaged app or not. | ||
| bool PushNotificationChannel::IsPackagedAppScenario() | ||
| { | ||
| return AppModel::Identity::IsPackagedProcess() && IsBackgroundTaskBuilderAvailable(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. See LICENSE in the project root for license information. | ||
|
|
||
| #pragma once | ||
| #include "pch.h" | ||
| #include <winrt/base.h> | ||
| #include <winrt/Windows.ApplicationModel.background.h> | ||
|
|
||
| struct PushNotificationDummyDeferral : winrt::implements <PushNotificationDummyDeferral, winrt::Windows::ApplicationModel::Background::IBackgroundTaskDeferral> | ||
| { | ||
| PushNotificationDummyDeferral() {} | ||
|
|
||
| void Complete() { }; | ||
| }; | ||
|
|
||
| struct PushNotificationDummyDeferralFactory : winrt::implements<PushNotificationDummyDeferralFactory, IClassFactory> | ||
| { | ||
| 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<PushNotificationDummyDeferral>().as(interfaceId, object); | ||
| } | ||
|
|
||
| HRESULT __stdcall LockServer(BOOL) noexcept final | ||
| { | ||
| return S_OK; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,12 +6,27 @@ import "ocidl.idl"; | |
|
|
||
| #include "../PushNotifications-Constants.h" | ||
|
|
||
| [object] | ||
| [uuid(25604D55-9B17-426F-9D67-2B11B3A65598)] | ||
| [pointer_default(unique)] | ||
| interface IWpnForegroundSink : IUnknown | ||
| { | ||
| HRESULT InvokeAll([in] ULONG length, [in, size_is(length)] byte* data, [out] BOOL* foregroundHandled); | ||
| }; | ||
|
|
||
| [object] | ||
| [uuid(60FC21B2-B396-4D49-94F0-7555869FB93C)] | ||
| [pointer_default(unique)] | ||
| interface INotificationsLongRunningPlatform : IUnknown | ||
| { | ||
| HRESULT RegisterFullTrustApplication([in] LPCWSTR processName, [in] GUID remoteId, [out] GUID* appId); | ||
|
|
||
| HRESULT RegisterForegroundActivator([in] IWpnForegroundSink* sink, [in] LPCWSTR processName); | ||
|
|
||
| HRESULT UnregisterForegroundActivator([in] LPCWSTR processName); | ||
|
|
||
| HRESULT SendBackgroundNotification([in] LPCWSTR processName, [in] ULONG length, [in, size_is(length)] byte* data); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please remove from idl. No longer being used anywhere. |
||
|
|
||
| }; | ||
|
|
||
| [uuid(PUSHNOTIFICATIONS_LIBID_UUID)] | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: From a clarity perspective, prefer that we don't rely on int to bool conversion. Better to say != 0 or > 0 and convert it into the bool equivalent.