-
Notifications
You must be signed in to change notification settings - Fork 55
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
API Review: Web Notification #3186
base: main
Are you sure you want to change the base?
Changes from 1 commit
1c1d3d0
952a757
e03a214
cbd9d61
5e22e5f
0b9a618
61d7ae7
c61f653
b8395cb
88418d0
0b6a3aa
25207b4
8ef88d3
4908aaf
993fe9f
320baf0
16ba2bc
4493c00
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -32,8 +32,11 @@ Runtime. | |||||
## Handle PermissionRequested event | ||||||
|
||||||
This can be achieved with the existing `PermissionRequested` events. | ||||||
`PermissionRequested` event used to not be raised for `PermissionKind.Notification`. | ||||||
Now, `PermissionRequested` events are raised for `PermissionKind.Notification`, and `PermissionState` needs to be set `Allow` explicitly to allow such permission requests. `PermissionState.Default` for `PermissionKind.Notification` is considered denied. | ||||||
`PermissionRequested` event used to not be raised for | ||||||
`PermissionKind.Notification`. Now, `PermissionRequested` events are raised for | ||||||
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. Does this mean that adding NotificationReceived event is a breaking change for some apps? 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. Yes technically, but it falls into the same category as adding a new enum value to an existing enum and we're not worried about that case - documenting that for the PermissionRequested event we'll be adding new enum values in the future and to have an appropriate value in the switch default. |
||||||
`PermissionKind.Notification`, and `PermissionState` needs to be set `Allow` | ||||||
explicitly to allow such permission requests. `PermissionState.Default` for | ||||||
`PermissionKind.Notification` is considered denied. | ||||||
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. How does this affect apps that predate the new behavior? They presumably ignore the PermissionKind.Notification request. I assume the system default behavior is to display a prompt and let the user decide whether to allow; i.e., same as before. 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. See above. |
||||||
|
||||||
### C# Sample | ||||||
```csharp | ||||||
|
@@ -66,9 +69,11 @@ void WebView_PermissionRequested(object sender, CoreWebView2PermissionRequestedE | |||||
{ | ||||||
case MessageBoxResult.Yes: | ||||||
args.State = CoreWebView2PermissionState.Allow; | ||||||
_cachedPermissions[cachedKey] = true; | ||||||
break; | ||||||
case MessageBoxResult.No: | ||||||
args.State = CoreWebView2PermissionState.Deny; | ||||||
_cachedPermissions[cachedKey] = false; | ||||||
break; | ||||||
case MessageBoxResult.Cancel: | ||||||
args.State = CoreWebView2PermissionState.Default; | ||||||
|
@@ -169,11 +174,15 @@ using Microsoft.Toolkit.Uwp.Notifications; | |||||
void WebView_NotificationReceived(object sender, CoreWebView2NotificationReceivedEventArgs args) | ||||||
{ | ||||||
CoreWebView2Deferral deferral = args.GetDeferral(); | ||||||
args.Handled = true; | ||||||
var notification = args.Notification; | ||||||
|
||||||
// Show notification with local MessageBox | ||||||
string message = "Received notification from " + args.Uri + " with body " + notification.Body; | ||||||
MessageBox.Show(message); | ||||||
System.Threading.SynchronizationContext.Current.Post((_) => | ||||||
{ | ||||||
string message = "Received notification from " + args.Uri + " with body " + notification.Body; | ||||||
MessageBox.Show(message); | ||||||
} | ||||||
|
||||||
// Requires Microsoft.Toolkit.Uwp.Notifications NuGet package version 7.0 or greater | ||||||
var toastContent = new ToastContentBuilder() | ||||||
|
@@ -183,15 +192,25 @@ void WebView_NotificationReceived(object sender, CoreWebView2NotificationReceive | |||||
toastContent.Show(); | ||||||
// See | ||||||
// https://learn.microsoft.com/windows/apps/design/shell/tiles-and-notifications/send-local-toast?tabs=uwp | ||||||
// for how to handle toast activation | ||||||
// for how to handle toast activation. | ||||||
|
||||||
// Call ReportShown after showing the toast notification to raise | ||||||
// the DOM notification.show event. | ||||||
// args.Handled has been set to true before we call Report... methods. | ||||||
notification.ReportShown(); | ||||||
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. Is this correct? The notification may not be shown immediately, and it might never be shown at all. I don't know what the DOM requirements are for the 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 investigate.
peiche-jessica marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
// During the toast notification activation handling, we may call | ||||||
// ReportClicked and/or ReportClose accordingly. | ||||||
notification.ReportClosed(); | ||||||
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. Shouldn't we validate that the 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. See previous comment about m_id 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. Named ReportClosedAsync/ReportClickedAsync in the IDL. 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. No longer async after changes above. Please ensure correct after all other changes are complete =) 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. Is it an error to Report redundant or conflicting actions?
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 update docs and implementation to match what Raymond says above. Should match the error case for not setting Handled and then calling a Report method. |
||||||
args.Handled = true; | ||||||
} | ||||||
``` | ||||||
|
||||||
### C++ Sample | ||||||
|
||||||
`Microsoft.Toolkit.Uwp.Notifications ` package does not work with non-UWP Win32 | ||||||
app. Hence in the sample code we use native MessageBox and handle notifications | ||||||
accordingly. | ||||||
|
||||||
```cpp | ||||||
... | ||||||
{ | ||||||
|
@@ -203,16 +222,21 @@ void WebView_NotificationReceived(object sender, CoreWebView2NotificationReceive | |||||
ICoreWebView2* sender, | ||||||
ICoreWebView2NotificationReceivedEventArgs* args) -> HRESULT | ||||||
{ | ||||||
// Block notifications from specific URIs and set Handled to | ||||||
// false so the the default notification UI will not be | ||||||
// shown by WebView2 either. | ||||||
wil::unique_cotaskmem_string uri; | ||||||
CHECK_FAILURE(args->get_Uri(&uri); | ||||||
if (ShouldBlockUri(uri.get())) | ||||||
// Setting Handled to TRUE so the the default notification UI will not be | ||||||
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.
Suggested change
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 fix wording. |
||||||
// shown by WebView2 as we are handling the notification ourselves. | ||||||
// Block notifications from specific origins and return directly without showing notifications. | ||||||
CHECK_FAILURE(args->put_Handled(TRUE)); | ||||||
wil::unique_cotaskmem_string origin; | ||||||
CHECK_FAILURE(args->get_SenderOrigin(&origin)); | ||||||
if (ShouldBlockOrigin(origin.get())) | ||||||
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. This feature does not exist in the C# sample. The C# and C++ samples should show equivalent functionality. If the C++ sample has a feature that is not in the C# sample, then C# developers will assume that the feature is not available in C#. 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 update to ensure samples match. |
||||||
{ | ||||||
CHECK_FAILURE(args->put_Handled(FALSE)); | ||||||
return S_OK; | ||||||
} | ||||||
ShowNotification(args); | ||||||
|
||||||
wil::com_ptr<ICoreWebView2Notification> notification; | ||||||
CHECK_FAILURE(args->get_Notification(¬ification)); | ||||||
|
||||||
ShowNotification(notification); | ||||||
return S_OK; | ||||||
}) | ||||||
.Get(), | ||||||
|
@@ -222,40 +246,28 @@ void WebView_NotificationReceived(object sender, CoreWebView2NotificationReceive | |||||
... | ||||||
//! [OnNotificationReceived] | ||||||
void SettingsComponent::ShowNotification( | ||||||
ICoreWebView2NotificationReceivedEventArgs* args) | ||||||
ICoreWebView2Notification* notification) | ||||||
{ | ||||||
AppWindow* appWindow = m_appWindow; | ||||||
|
||||||
// Obtain a deferral for the event so that the CoreWebView2 | ||||||
// does not examine the properties we set on the event args and | ||||||
// after we call the Complete method asynchronously later. | ||||||
wil::com_ptr<ICoreWebView2Deferral> deferral; | ||||||
CHECK_FAILURE(args->GetDeferral(&deferral)); | ||||||
|
||||||
wil::com_ptr<ICoreWebView2NotificationReceivedEventArgs> eventArgs = args; | ||||||
|
||||||
appWindow->RunAsync( | ||||||
[this, eventArgs, deferral] | ||||||
[this, notification] | ||||||
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. use-after-free bug. Need to extend lifetime of the notification.
Suggested change
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 fix. |
||||||
{ | ||||||
wil::com_ptr<ICoreWebView2Notification> notification; | ||||||
CHECK_FAILURE(eventArgs->get_Notification(¬ification)); | ||||||
|
||||||
wil::unique_cotaskmem_string uri; | ||||||
CHECK_FAILURE(eventArgs->get_Uri(&uri)); | ||||||
wil::unique_cotaskmem_string origin; | ||||||
CHECK_FAILURE(eventArgs->get_SenderOrigin(&origin)); | ||||||
wil::unique_cotaskmem_string title; | ||||||
CHECK_FAILURE(notification->get_Title(&title)); | ||||||
wil::unique_cotaskmem_string body; | ||||||
CHECK_FAILURE(notification->get_Body(&body)); | ||||||
|
||||||
std::wstring message = | ||||||
L"The page at " + std::wstring(uri.get()) + L" sends you an | ||||||
L"The page from " + std::wstring(origin.get()) + L" sends you an | ||||||
notification:\n\n"; | ||||||
message += body.get(); | ||||||
notification->ReportShown(); | ||||||
int response = MessageBox(nullptr, message.c_str(), title.get(), MB_OKCANCEL); | ||||||
(response == IDOK) ? notification->ReportClicked() : notification->ReportClosed(); | ||||||
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. Completion callback parameters missing from ReportClosed and ReportClicked. 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 ensure correct after all other changes are done. |
||||||
|
||||||
deferral->Complete(); | ||||||
}); | ||||||
} | ||||||
//! [OnNotificationReceived] | ||||||
|
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.
Curiously, the documentation suggests that it is indeed raised:
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.
Please update docs to note which runtime version the notification permission event started being raised.