Bug 1848801 - Use system dismiss button for persistent notification r=nrishel,fluent-reviewers,bolsson

Per the documentation the system should handle `arguments=dismiss` to fire dismiss event but somehow it still fires activate event. This patch thus handles it manually while still taking advantage of the Windows provided localization of the button.

Differential Revision: https://phabricator.services.mozilla.com/D198286
This commit is contained in:
Kagami Sascha Rosylight 2024-01-12 22:16:31 +00:00
parent 2a3d7392c1
commit 1c6588f728
2 changed files with 26 additions and 8 deletions

View File

@ -140,8 +140,14 @@ static bool AddActionNode(ComPtr<IXmlDocument>& toastXml,
activationType);
NS_ENSURE_TRUE(success, false);
// No special argument handling: when `activationType="system"`, `action` is
// a Windows-specific keyword, generally "dismiss" or "snooze".
// No special argument handling: when `activationType="system"`, `arguments`
// should be a Windows-specific keyword, namely "dismiss" or "snooze", which
// are supposed to make a system handled dismiss/snooze buttons.
// https://learn.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/adaptive-interactive-toasts?tabs=xml#snoozedismiss
//
// Note that while using it prevents calling our notification COM server,
// it somehow still calls OnActivate instead of OnDismiss. Thus, we still
// need to handle such callbacks manually by checking `arguments`.
success = SetAttribute(action, HStringReference(L"arguments"), actionArgs);
NS_ENSURE_TRUE(success, false);
}
@ -664,8 +670,11 @@ ComPtr<IXmlDocument> ToastNotificationHandler::CreateToastXmlDocument() {
}
// Windows ignores scenario=reminder added by mRequiredInteraction if
// there's no non-contextmenu activationType=background action.
// there's no non-contextmenu action.
if (mRequireInteraction && !mActions.Length()) {
// `activationType="system" arguments="dismiss" content=""` provides
// localized text from Windows, but we support more locales than Windows
// does, so let's have our own.
nsTArray<nsCString> resIds = {
"toolkit/global/alert.ftl"_ns,
};
@ -678,7 +687,7 @@ ComPtr<IXmlDocument> ToastNotificationHandler::CreateToastXmlDocument() {
NS_ENSURE_TRUE(
AddActionNode(toastXml, actionsNode, NS_ConvertUTF8toUTF16(closeTitle),
launchArg, u""_ns, u""_ns, u"background"_ns),
u""_ns, u"dismiss"_ns, u""_ns, u"system"_ns),
nullptr);
}
@ -848,6 +857,7 @@ ToastNotificationHandler::OnActivate(
if (mAlertListener) {
// Extract the `action` value from the argument string.
nsAutoString argumentsString;
nsAutoString actionString;
if (inspectable) {
ComPtr<IToastActivatedEventArgs> eventArgs;
@ -862,6 +872,7 @@ ToastNotificationHandler::OnActivate(
MOZ_LOG(sWASLog, LogLevel::Info,
("OnActivate: arguments: %s",
NS_ConvertUTF16toUTF8(buffer).get()));
argumentsString.Assign(buffer);
// Toast arguments are a newline separated key/value combination of
// launch arguments and an optional action argument provided as an
@ -888,7 +899,14 @@ ToastNotificationHandler::OnActivate(
}
}
if (actionString.EqualsLiteral("settings")) {
if (argumentsString.EqualsLiteral("dismiss")) {
// XXX: Somehow Windows still fires OnActivate instead of OnDismiss for
// supposedly system managed dismiss button (with activationType=system
// and arguments=dismiss). We have to manually treat such callback as a
// dismiss action. For this case `arguments` only includes a keyword so we
// don't need to compare with a parsed result.
SendFinished();
} else if (actionString.EqualsLiteral("settings")) {
mAlertListener->Observe(nullptr, "alertsettingscallback", mCookie.get());
} else if (actionString.EqualsLiteral("snooze")) {
mAlertListener->Observe(nullptr, "alertdisablecallback", mCookie.get());

View File

@ -287,7 +287,7 @@ function testAlert(when, { serverEnabled, profD, isBackgroundTaskMode } = {}) {
);
alert = makeAlert({ name, title, text, imageURL, requireInteraction: true });
expected = `<toast scenario="reminder" launch="launch"><visual><binding template="ToastImageAndText03"><image id="1" src="file:///image.png"/><text id="1">title</text><text id="2">text</text></binding></visual><actions>${settingsAction}<action content="Dismiss"/></actions></toast>`;
expected = `<toast scenario="reminder" launch="launch"><visual><binding template="ToastImageAndText03"><image id="1" src="file:///image.png"/><text id="1">title</text><text id="2">text</text></binding></visual><actions>${settingsAction}<action content="Dismiss" arguments="dismiss" activationType="system"/></actions></toast>`;
Assert.deepEqual(
[
expected.replace("<actions></actions>", "<actions/>"),
@ -300,8 +300,8 @@ function testAlert(when, { serverEnabled, profD, isBackgroundTaskMode } = {}) {
"Dismiss",
{
content: "Dismiss",
arguments: { "": undefined },
activationType: "background",
arguments: "dismiss",
activationType: "system",
},
],
].filter(x => x.length)