From 82fd68b985ca0cc0d27f2238e310deb6e3f0564b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Fri, 15 May 2020 15:28:17 +0200 Subject: [PATCH] notificationDaemon: Fix grouping by PID For fd.o notifications, we are taking the sender's PID into account when associating notifications with sources (mainly to deal with notify-send). This broke when the implementation under the well-known name was moved into a separate service, as the implementation in gnome-shell will now always see the public notification-daemon as sender. Restore the old behavior by resolving the sender PID in the separate service, and pass it as hint to the implementation in gnome-shell. https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2592 --- .../notifications/notificationDaemon.js | 27 +++++++++- js/ui/notificationDaemon.js | 50 ++----------------- 2 files changed, 29 insertions(+), 48 deletions(-) diff --git a/js/dbusServices/notifications/notificationDaemon.js b/js/dbusServices/notifications/notificationDaemon.js index c2d2ef6f9..bf0f85b1c 100644 --- a/js/dbusServices/notifications/notificationDaemon.js +++ b/js/dbusServices/notifications/notificationDaemon.js @@ -9,6 +9,8 @@ const { ServiceImplementation } = imports.dbusService; const NotificationsIface = loadInterfaceXML('org.freedesktop.Notifications'); const NotificationsProxy = Gio.DBusProxy.makeProxyWrapper(NotificationsIface); +Gio._promisify(Gio.DBusConnection.prototype, 'call', 'call_finish'); + var NotificationDaemon = class extends ServiceImplementation { constructor() { super(NotificationsIface, '/org/freedesktop/Notifications'); @@ -42,7 +44,15 @@ var NotificationDaemon = class extends ServiceImplementation { null, null); } - NotifyAsync(params, invocation) { + async NotifyAsync(params, invocation) { + const pid = await this._getSenderPid(invocation.get_sender()); + const hints = params[6]; + + params[6] = { + ...hints, + 'sender-pid': new GLib.Variant('u', pid), + }; + this._proxy.NotifyRemote(...params, (res, error) => { if (this._handleError(invocation, error)) return; @@ -77,4 +87,19 @@ var NotificationDaemon = class extends ServiceImplementation { invocation.return_value(new GLib.Variant('(ssss)', res)); }); } + + async _getSenderPid(sender) { + const res = await Gio.DBus.session.call( + 'org.freedesktop.DBus', + '/', + 'org.freedesktop.DBus', + 'GetConnectionUnixProcessID', + new GLib.Variant('(s)', [sender]), + new GLib.VariantType('(u)'), + Gio.DBusCallFlags.NONE, + -1, + null); + const [pid] = res.deepUnpack(); + return pid; + } }; diff --git a/js/ui/notificationDaemon.js b/js/ui/notificationDaemon.js index 3331355ab..28fe8ba06 100644 --- a/js/ui/notificationDaemon.js +++ b/js/ui/notificationDaemon.js @@ -10,13 +10,6 @@ const Params = imports.misc.params; const { loadInterfaceXML } = imports.misc.fileUtils; -// Should really be defined in Gio.js -const BusIface = loadInterfaceXML('org.freedesktop.DBus'); -var BusProxy = Gio.DBusProxy.makeProxyWrapper(BusIface); -function Bus() { - return new BusProxy(Gio.DBus.session, 'org.freedesktop.DBus', '/org/freedesktop/DBus'); -} - const FdoNotificationsIface = loadInterfaceXML('org.freedesktop.Notifications'); var NotificationClosedReason = { @@ -49,9 +42,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon { this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications'); this._sources = []; - this._senderToPid = {}; this._notifications = {}; - this._busProxy = new Bus(); this._nextNotificationId = 1; @@ -116,12 +107,9 @@ var FdoNotificationDaemon = class FdoNotificationDaemon { // // If no existing source is found, a new source is created as long as // pid is provided. - // - // Either a pid or ndata.notification is needed to retrieve or - // create a source. _getSource(title, pid, ndata, sender) { if (!pid && !(ndata && ndata.notification)) - return null; + throw new Error('Either a pid or ndata.notification is needed'); // We use notification's source for the notifications we still have // around that are getting replaced because we don't keep sources @@ -218,42 +206,10 @@ var FdoNotificationDaemon = class FdoNotificationDaemon { this._notifications[id] = ndata; let sender = invocation.get_sender(); - let pid = this._senderToPid[sender]; + let pid = hints['sender-pid']; let source = this._getSource(appName, pid, ndata, sender, null); - - if (source) { - this._notifyForSource(source, ndata); - return invocation.return_value(GLib.Variant.new('(u)', [id])); - } - - if (replacesId) { - // There's already a pending call to GetConnectionUnixProcessID, - // which will see the new notification data when it finishes, - // so we don't have to do anything. - return invocation.return_value(GLib.Variant.new('(u)', [id])); - } - - this._busProxy.GetConnectionUnixProcessIDRemote(sender, (result, excp) => { - // The app may have updated or removed the notification - ndata = this._notifications[id]; - if (!ndata) - return; - - if (excp) { - logError(excp, 'Call to GetConnectionUnixProcessID failed'); - return; - } - - [pid] = result; - source = this._getSource(appName, pid, ndata, sender, null); - - this._senderToPid[sender] = pid; - source.connect('destroy', () => { - delete this._senderToPid[sender]; - }); - this._notifyForSource(source, ndata); - }); + this._notifyForSource(source, ndata); return invocation.return_value(GLib.Variant.new('(u)', [id])); }