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
This commit is contained in:
parent
3ad2baede0
commit
e74e691d84
@ -9,6 +9,8 @@ const { ServiceImplementation } = imports.dbusService;
|
|||||||
const NotificationsIface = loadInterfaceXML('org.freedesktop.Notifications');
|
const NotificationsIface = loadInterfaceXML('org.freedesktop.Notifications');
|
||||||
const NotificationsProxy = Gio.DBusProxy.makeProxyWrapper(NotificationsIface);
|
const NotificationsProxy = Gio.DBusProxy.makeProxyWrapper(NotificationsIface);
|
||||||
|
|
||||||
|
Gio._promisify(Gio.DBusConnection.prototype, 'call', 'call_finish');
|
||||||
|
|
||||||
var NotificationDaemon = class extends ServiceImplementation {
|
var NotificationDaemon = class extends ServiceImplementation {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(NotificationsIface, '/org/freedesktop/Notifications');
|
super(NotificationsIface, '/org/freedesktop/Notifications');
|
||||||
@ -42,7 +44,15 @@ var NotificationDaemon = class extends ServiceImplementation {
|
|||||||
null, null);
|
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) => {
|
this._proxy.NotifyRemote(...params, (res, error) => {
|
||||||
if (this._handleError(invocation, error))
|
if (this._handleError(invocation, error))
|
||||||
return;
|
return;
|
||||||
@ -77,4 +87,19 @@ var NotificationDaemon = class extends ServiceImplementation {
|
|||||||
invocation.return_value(new GLib.Variant('(ssss)', res));
|
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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -10,13 +10,6 @@ const Params = imports.misc.params;
|
|||||||
|
|
||||||
const { loadInterfaceXML } = imports.misc.fileUtils;
|
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');
|
const FdoNotificationsIface = loadInterfaceXML('org.freedesktop.Notifications');
|
||||||
|
|
||||||
var NotificationClosedReason = {
|
var NotificationClosedReason = {
|
||||||
@ -49,9 +42,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
|
|||||||
this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications');
|
this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications');
|
||||||
|
|
||||||
this._sources = [];
|
this._sources = [];
|
||||||
this._senderToPid = {};
|
|
||||||
this._notifications = {};
|
this._notifications = {};
|
||||||
this._busProxy = new Bus();
|
|
||||||
|
|
||||||
this._nextNotificationId = 1;
|
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
|
// If no existing source is found, a new source is created as long as
|
||||||
// pid is provided.
|
// pid is provided.
|
||||||
//
|
|
||||||
// Either a pid or ndata.notification is needed to retrieve or
|
|
||||||
// create a source.
|
|
||||||
_getSource(title, pid, ndata, sender) {
|
_getSource(title, pid, ndata, sender) {
|
||||||
if (!pid && !(ndata && ndata.notification))
|
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
|
// We use notification's source for the notifications we still have
|
||||||
// around that are getting replaced because we don't keep sources
|
// around that are getting replaced because we don't keep sources
|
||||||
@ -218,42 +206,10 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
|
|||||||
this._notifications[id] = ndata;
|
this._notifications[id] = ndata;
|
||||||
|
|
||||||
let sender = invocation.get_sender();
|
let sender = invocation.get_sender();
|
||||||
let pid = this._senderToPid[sender];
|
let pid = hints['sender-pid'];
|
||||||
|
|
||||||
let source = this._getSource(appName, pid, ndata, sender, null);
|
let source = this._getSource(appName, pid, ndata, sender, null);
|
||||||
|
|
||||||
if (source) {
|
|
||||||
this._notifyForSource(source, ndata);
|
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);
|
|
||||||
});
|
|
||||||
|
|
||||||
return invocation.return_value(GLib.Variant.new('(u)', [id]));
|
return invocation.return_value(GLib.Variant.new('(u)', [id]));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user