gnome-shell/js/dbusServices/notifications/notificationDaemon.js
Florian Müllner 5442266f28 js: Simplify promisify() calls
If the finish function isn't specified, promisify will now try
to use the async name without '_async'/'_begin' suffix (if any)
and '_finish' appended.

Everything except IBus uses a variation of that pattern, so there's
quite a bit of boilerplate we get to remove…

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2174>
2022-02-11 16:24:01 +00:00

162 lines
4.8 KiB
JavaScript

// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported NotificationDaemon */
const { Gio, GLib } = imports.gi;
const { loadInterfaceXML } = imports.misc.fileUtils;
const { ServiceImplementation } = imports.dbusService;
const NotificationsIface = loadInterfaceXML('org.freedesktop.Notifications');
const NotificationsProxy = Gio.DBusProxy.makeProxyWrapper(NotificationsIface);
Gio._promisify(Gio.DBusConnection.prototype, 'call');
var NotificationDaemon = class extends ServiceImplementation {
constructor() {
super(NotificationsIface, '/org/freedesktop/Notifications');
this._autoShutdown = false;
this._activeNotifications = new Map();
this._proxy = new NotificationsProxy(Gio.DBus.session,
'org.gnome.Shell',
'/org/freedesktop/Notifications',
(proxy, error) => {
if (error)
log(error.message);
});
this._proxy.connectSignal('ActionInvoked',
(proxy, sender, params) => {
const [id] = params;
this._emitSignal(
this._activeNotifications.get(id),
'ActionInvoked',
new GLib.Variant('(us)', params));
});
this._proxy.connectSignal('NotificationClosed',
(proxy, sender, params) => {
const [id] = params;
this._emitSignal(
this._activeNotifications.get(id),
'NotificationClosed',
new GLib.Variant('(uu)', params));
this._activeNotifications.delete(id);
});
}
_emitSignal(sender, signalName, params) {
if (!sender)
return;
this._dbusImpl.get_connection()?.emit_signal(
sender,
this._dbusImpl.get_object_path(),
'org.freedesktop.Notifications',
signalName,
params);
}
_untrackSender(sender) {
super._untrackSender(sender);
this._activeNotifications.forEach((value, key) => {
if (value === sender)
this._activeNotifications.delete(key);
});
}
_checkNotificationId(invocation, id) {
if (id === 0)
return true;
if (!this._activeNotifications.has(id))
return true;
if (this._activeNotifications.get(id) === invocation.get_sender())
return true;
const error = new GLib.Error(Gio.DBusError,
Gio.DBusError.INVALID_ARGS, 'Invalid notification ID');
this._handleError(invocation, error);
return false;
}
register() {
Gio.DBus.session.own_name(
'org.freedesktop.Notifications',
Gio.BusNameOwnerFlags.REPLACE,
null, null);
}
async NotifyAsync(params, invocation) {
const sender = invocation.get_sender();
const pid = await this._getSenderPid(sender);
const replaceId = params[1];
const hints = params[6];
if (!this._checkNotificationId(invocation, replaceId))
return;
params[6] = {
...hints,
'sender-pid': new GLib.Variant('u', pid),
};
this._proxy.NotifyRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
const [id] = res;
this._activeNotifications.set(id, sender);
invocation.return_value(new GLib.Variant('(u)', res));
});
}
CloseNotificationAsync(params, invocation) {
const [id] = params;
if (!this._checkNotificationId(invocation, id))
return;
this._proxy.CloseNotificationRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(null);
});
}
GetCapabilitiesAsync(params, invocation) {
this._proxy.GetCapabilitiesRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
invocation.return_value(new GLib.Variant('(as)', res));
});
}
GetServerInformationAsync(params, invocation) {
this._proxy.GetServerInformationRemote(...params, (res, error) => {
if (this._handleError(invocation, error))
return;
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;
}
};