summaryrefslogtreecommitdiff
path: root/raveos-gnome-theme/theme-data/extensions/installed/appindicatorsupport@rgcjonas.gmail.com/dbusUtils.js
diff options
context:
space:
mode:
Diffstat (limited to 'raveos-gnome-theme/theme-data/extensions/installed/appindicatorsupport@rgcjonas.gmail.com/dbusUtils.js')
-rw-r--r--raveos-gnome-theme/theme-data/extensions/installed/appindicatorsupport@rgcjonas.gmail.com/dbusUtils.js121
1 files changed, 121 insertions, 0 deletions
diff --git a/raveos-gnome-theme/theme-data/extensions/installed/appindicatorsupport@rgcjonas.gmail.com/dbusUtils.js b/raveos-gnome-theme/theme-data/extensions/installed/appindicatorsupport@rgcjonas.gmail.com/dbusUtils.js
new file mode 100644
index 0000000..d4d7a96
--- /dev/null
+++ b/raveos-gnome-theme/theme-data/extensions/installed/appindicatorsupport@rgcjonas.gmail.com/dbusUtils.js
@@ -0,0 +1,121 @@
+// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+import Gio from 'gi://Gio';
+import GLib from 'gi://GLib';
+
+import {Logger} from './logger.js';
+
+export const BUS_ADDRESS_REGEX = /([a-zA-Z0-9._-]+\.[a-zA-Z0-9.-]+)|(:[0-9]+\.[0-9]+)$/;
+
+Gio._promisify(Gio.DBusConnection.prototype, 'call');
+
+export async function getUniqueBusName(bus, name, cancellable) {
+ if (name[0] === ':')
+ return name;
+
+ if (!bus)
+ bus = Gio.DBus.session;
+
+ const variantName = new GLib.Variant('(s)', [name]);
+ const [unique] = (await bus.call('org.freedesktop.DBus', '/', 'org.freedesktop.DBus',
+ 'GetNameOwner', variantName, new GLib.VariantType('(s)'),
+ Gio.DBusCallFlags.NONE, -1, cancellable)).deep_unpack();
+
+ return unique;
+}
+
+export async function getBusNames(bus, cancellable) {
+ if (!bus)
+ bus = Gio.DBus.session;
+
+ const [names] = (await bus.call('org.freedesktop.DBus', '/', 'org.freedesktop.DBus',
+ 'ListNames', null, new GLib.VariantType('(as)'), Gio.DBusCallFlags.NONE,
+ -1, cancellable)).deep_unpack();
+
+ const uniqueNames = new Map();
+ const requests = names.map(name => getUniqueBusName(bus, name, cancellable));
+ const results = await Promise.allSettled(requests);
+
+ for (let i = 0; i < results.length; i++) {
+ const result = results[i];
+ if (result.status === 'fulfilled') {
+ let namesForBus = uniqueNames.get(result.value);
+ if (!namesForBus) {
+ namesForBus = new Set();
+ uniqueNames.set(result.value, namesForBus);
+ }
+ if (result.value !== names[i])
+ namesForBus.add(names[i]);
+ } else if (!result.reason.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
+ Logger.debug(`Impossible to get the unique name of ${names[i]}: ${result.reason}`);
+ }
+ }
+
+ return uniqueNames;
+}
+
+async function getProcessId(connectionName, cancellable = null, bus = Gio.DBus.session) {
+ const res = await bus.call('org.freedesktop.DBus', '/',
+ 'org.freedesktop.DBus', 'GetConnectionUnixProcessID',
+ new GLib.Variant('(s)', [connectionName]),
+ new GLib.VariantType('(u)'),
+ Gio.DBusCallFlags.NONE,
+ -1,
+ cancellable);
+ const [pid] = res.deepUnpack();
+ return pid;
+}
+
+export async function getProcessName(connectionName, cancellable = null,
+ priority = GLib.PRIORITY_DEFAULT, bus = Gio.DBus.session) {
+ const pid = await getProcessId(connectionName, cancellable, bus);
+ const cmdFile = Gio.File.new_for_path(`/proc/${pid}/cmdline`);
+ const inputStream = await cmdFile.read_async(priority, cancellable);
+ const bytes = await inputStream.read_bytes_async(2048, priority, cancellable);
+ const textDecoder = new TextDecoder();
+ return textDecoder.decode(bytes.toArray().map(v => !v ? 0x20 : v));
+}
+
+export async function* introspectBusObject(bus, name, cancellable,
+ interfaces = undefined, path = undefined) {
+ if (!path)
+ path = '/';
+
+ const [introspection] = (await bus.call(name, path, 'org.freedesktop.DBus.Introspectable',
+ 'Introspect', null, new GLib.VariantType('(s)'), Gio.DBusCallFlags.NONE,
+ 5000, cancellable)).deep_unpack();
+
+ const nodeInfo = Gio.DBusNodeInfo.new_for_xml(introspection);
+
+ if (!interfaces || dbusNodeImplementsInterfaces(nodeInfo, interfaces))
+ yield {nodeInfo, path};
+
+ if (path === '/')
+ path = '';
+
+ for (const subNodeInfo of nodeInfo.nodes) {
+ const subPath = `${path}/${subNodeInfo.path}`;
+ yield* introspectBusObject(bus, name, cancellable, interfaces, subPath);
+ }
+}
+
+function dbusNodeImplementsInterfaces(nodeInfo, interfaces) {
+ if (!(nodeInfo instanceof Gio.DBusNodeInfo) || !Array.isArray(interfaces))
+ return false;
+
+ return interfaces.some(iface => nodeInfo.lookup_interface(iface));
+}