Bug 1952462 - Part 1: Add NotificationEvent.action r=asuth

Differential Revision: https://phabricator.services.mozilla.com/D241083
This commit is contained in:
Kagami Sascha Rosylight
2025-03-14 06:25:03 +00:00
parent a0951b58f5
commit e0242c68ed
11 changed files with 100 additions and 50 deletions

View File

@@ -300,7 +300,8 @@ interface nsIServiceWorkerManager : nsISupports
[noscript]
void sendNotificationClickEvent(in ACString aOriginSuffix,
in AString scope,
in const_IPCNotificationRef aNotification);
in const_IPCNotificationRef aNotification,
in AString aAction);
[noscript]
void sendNotificationCloseEvent(in ACString aOriginSuffix,

View File

@@ -30,7 +30,7 @@ NotificationParent::Observe(nsISupports* aSubject, const char* aTopic,
return OpenSettings(mPrincipal);
}
if (!strcmp("alertclickcallback", aTopic)) {
return FireClickEvent();
return FireClickEvent(aSubject);
}
if (!strcmp("alertshow", aTopic)) {
if (!mResolver) {
@@ -83,7 +83,7 @@ NotificationParent::Observe(nsISupports* aSubject, const char* aTopic,
return NS_OK;
}
nsresult NotificationParent::FireClickEvent() {
nsresult NotificationParent::FireClickEvent(nsISupports* aSubject) {
if (mScope.IsEmpty()) {
if (SendNotifyClick()) {
return NS_OK;
@@ -96,10 +96,16 @@ nsresult NotificationParent::FireClickEvent() {
// context but in the window context
if (nsCOMPtr<nsIServiceWorkerManager> swm =
mozilla::components::ServiceWorkerManager::Service()) {
nsCOMPtr<nsIAlertAction> action = do_QueryInterface(aSubject);
nsAutoString actionName;
if (action) {
MOZ_TRY(action->GetAction(actionName));
}
nsAutoCString originSuffix;
MOZ_TRY(mPrincipal->GetOriginSuffix(originSuffix));
MOZ_TRY(swm->SendNotificationClickEvent(originSuffix, mScope,
IPCNotification(mId, mOptions)));
MOZ_TRY(swm->SendNotificationClickEvent(
originSuffix, mScope, IPCNotification(mId, mOptions), actionName));
return NS_OK;
}

View File

@@ -48,7 +48,7 @@ class NotificationParent final : public PNotificationParent,
~NotificationParent() = default;
nsresult Show();
nsresult FireClickEvent();
nsresult FireClickEvent(nsISupports* aSubject);
nsresult FireCloseEvent();
void Unregister(CloseMode aCloseMode);

View File

@@ -1129,9 +1129,10 @@ ServiceWorkerManager::SendPushSubscriptionChangeEvent(
aOldSubscription);
}
nsresult ServiceWorkerManager::SendNotificationEvent(
const nsAString& aEventName, const nsACString& aOriginSuffix,
const nsAString& aScope, const IPCNotification& aNotification) {
NS_IMETHODIMP
ServiceWorkerManager::SendNotificationClickEvent(
const nsACString& aOriginSuffix, const nsAString& aScope,
const IPCNotification& aNotification, const nsAString& aAction) {
OriginAttributes attrs;
if (!attrs.PopulateFromSuffix(aOriginSuffix)) {
return NS_ERROR_INVALID_ARG;
@@ -1145,24 +1146,28 @@ nsresult ServiceWorkerManager::SendNotificationEvent(
ServiceWorkerPrivate* workerPrivate = info->WorkerPrivate();
return workerPrivate->SendNotificationEvent(aEventName, aScope,
aNotification);
}
NS_IMETHODIMP
ServiceWorkerManager::SendNotificationClickEvent(
const nsACString& aOriginSuffix, const nsAString& aScope,
const IPCNotification& aIPCNotification) {
return SendNotificationEvent(nsLiteralString(NOTIFICATION_CLICK_EVENT_NAME),
aOriginSuffix, aScope, aIPCNotification);
return workerPrivate->SendNotificationClickEvent(aScope, aNotification,
aAction);
}
NS_IMETHODIMP
ServiceWorkerManager::SendNotificationCloseEvent(
const nsACString& aOriginSuffix, const nsAString& aScope,
const IPCNotification& aIPCNotification) {
return SendNotificationEvent(nsLiteralString(NOTIFICATION_CLOSE_EVENT_NAME),
aOriginSuffix, aScope, aIPCNotification);
const IPCNotification& aNotification) {
OriginAttributes attrs;
if (!attrs.PopulateFromSuffix(aOriginSuffix)) {
return NS_ERROR_INVALID_ARG;
}
ServiceWorkerInfo* info =
GetActiveWorkerInfoForScope(attrs, NS_ConvertUTF16toUTF8(aScope));
if (!info) {
return NS_ERROR_FAILURE;
}
ServiceWorkerPrivate* workerPrivate = info->WorkerPrivate();
return workerPrivate->SendNotificationCloseEvent(aScope, aNotification);
}
RefPtr<ServiceWorkerRegistrationPromise> ServiceWorkerManager::WhenReady(

View File

@@ -429,11 +429,6 @@ class ServiceWorkerManager final : public nsIServiceWorkerManager,
void MaybeSendUnregister(nsIPrincipal* aPrincipal, const nsACString& aScope);
nsresult SendNotificationEvent(const nsAString& aEventName,
const nsACString& aOriginSuffix,
const nsAString& aScope,
const IPCNotification& aNotification);
// Used by remove() and removeAll() when clearing history.
// MUST ONLY BE CALLED FROM UnregisterIfMatchesHost!
void ForceUnregister(RegistrationDataPerPrincipal* aRegistrationData,

View File

@@ -956,9 +956,19 @@ class NotificationEventOp : public ExtendableEventOp,
ServiceWorkerNotificationEventOpArgs& args =
mArgs.get_ServiceWorkerNotificationEventOpArgs();
bool isClick = args.type() ==
ServiceWorkerNotificationEventOpArgs::
TServiceWorkerNotificationClickEventOpArgs;
const IPCNotification& notification =
args.type() == ServiceWorkerNotificationEventOpArgs::
TServiceWorkerNotificationClickEventOpArgs
? args.get_ServiceWorkerNotificationClickEventOpArgs()
.notification()
: args.get_ServiceWorkerNotificationCloseEventOpArgs()
.notification();
auto result = Notification::ConstructFromIPC(
aWorkerPrivate->GlobalScope(), args.notification(),
aWorkerPrivate->GlobalScope(), notification,
NS_ConvertUTF8toUTF16(aWorkerPrivate->ServiceWorkerScope()));
if (NS_WARN_IF(result.isErr())) {
@@ -969,13 +979,19 @@ class NotificationEventOp : public ExtendableEventOp,
init.mNotification = result.unwrap();
init.mBubbles = false;
init.mCancelable = false;
if (isClick) {
init.mAction =
args.get_ServiceWorkerNotificationClickEventOpArgs().action();
}
RefPtr<NotificationEvent> notificationEvent =
NotificationEvent::Constructor(target, args.eventName(), init);
NotificationEvent::Constructor(
target, isClick ? u"notificationclick"_ns : u"notificationclose"_ns,
init);
notificationEvent->SetTrusted(true);
if (args.eventName().EqualsLiteral("notificationclick")) {
if (isClick) {
StartClearWindowTimer(aWorkerPrivate);
}

View File

@@ -53,9 +53,18 @@ struct ServiceWorkerPushSubscriptionChangeEventOpArgs {
PushSubscriptionData? oldSubscription;
};
struct ServiceWorkerNotificationEventOpArgs {
nsString eventName;
struct ServiceWorkerNotificationClickEventOpArgs {
IPCNotification notification;
nsString action;
};
struct ServiceWorkerNotificationCloseEventOpArgs {
IPCNotification notification;
};
union ServiceWorkerNotificationEventOpArgs {
ServiceWorkerNotificationClickEventOpArgs;
ServiceWorkerNotificationCloseEventOpArgs;
};
struct ServiceWorkerExtensionAPIEventOpArgs {

View File

@@ -984,20 +984,32 @@ nsresult ServiceWorkerPrivate::SendPushSubscriptionChangeEvent(
});
}
nsresult ServiceWorkerPrivate::SendNotificationEvent(
const nsAString& aEventName, const nsAString& aScope,
const IPCNotification& aNotification) {
nsresult ServiceWorkerPrivate::SendNotificationClickEvent(
const nsAString& aScope, const IPCNotification& aNotification,
const nsAString& aAction) {
MOZ_ASSERT(NS_IsMainThread());
if (!aEventName.EqualsLiteral(NOTIFICATION_CLICK_EVENT_NAME) &&
!aEventName.EqualsLiteral(NOTIFICATION_CLOSE_EVENT_NAME)) {
MOZ_ASSERT_UNREACHABLE("Invalid notification event name");
return NS_ERROR_FAILURE;
}
ServiceWorkerNotificationClickEventOpArgs clickArgs;
clickArgs.notification() = aNotification;
clickArgs.action() = aAction;
ServiceWorkerNotificationEventOpArgs args;
args.eventName() = nsString(aEventName);
args.notification() = aNotification;
ServiceWorkerNotificationEventOpArgs args(std::move(clickArgs));
return ExecServiceWorkerOp(
std::move(args), ServiceWorkerLifetimeExtension(FullLifetimeExtension{}),
[](ServiceWorkerOpResult&& aResult) {
MOZ_ASSERT(aResult.type() == ServiceWorkerOpResult::Tnsresult);
});
}
nsresult ServiceWorkerPrivate::SendNotificationCloseEvent(
const nsAString& aScope, const IPCNotification& aNotification) {
MOZ_ASSERT(NS_IsMainThread());
ServiceWorkerNotificationCloseEventOpArgs closeArgs;
closeArgs.notification() = aNotification;
ServiceWorkerNotificationEventOpArgs args(std::move(closeArgs));
return ExecServiceWorkerOp(
std::move(args), ServiceWorkerLifetimeExtension(FullLifetimeExtension{}),

View File

@@ -111,9 +111,12 @@ class ServiceWorkerPrivate final : public RemoteWorkerObserver {
nsresult SendPushSubscriptionChangeEvent(
const RefPtr<nsIPushSubscription>& aOldSubscription);
nsresult SendNotificationEvent(const nsAString& aEventName,
const nsAString& aScope,
const IPCNotification& aNotification);
nsresult SendNotificationClickEvent(const nsAString& aScope,
const IPCNotification& aNotification,
const nsAString& aAction);
nsresult SendNotificationCloseEvent(const nsAString& aScope,
const IPCNotification& aNotification);
nsresult SendFetchEvent(nsCOMPtr<nsIInterceptedChannel> aChannel,
nsILoadGroup* aLoadGroup, const nsAString& aClientId,

View File

@@ -11,14 +11,20 @@
* related or neighboring rights to this work.
*/
[Exposed=ServiceWorker,Func="mozilla::dom::Notification::PrefEnabled"]
[Exposed=ServiceWorker, Func="mozilla::dom::Notification::PrefEnabled"]
interface NotificationEvent : ExtendableEvent {
constructor(DOMString type, NotificationEventInit eventInitDict);
[BinaryName="notification_"]
readonly attribute Notification notification;
[Pref="dom.webnotifications.actions.enabled"]
readonly attribute DOMString action;
};
dictionary NotificationEventInit : ExtendableEventInit {
required Notification notification;
[Pref="dom.webnotifications.actions.enabled"]
DOMString action = "";
};

View File

@@ -5,9 +5,6 @@ prefs: [dom.webnotifications.requireinteraction.enabled:true, dom.webnotificatio
[Notification interface: attribute timestamp]
expected: FAIL
[NotificationEvent interface: attribute action]
expected: FAIL
[Notification interface: attribute image]
expected: FAIL