Hi there! I’m currently facing an issue trying to communicate with the “org.freedesktop.PolicyKit1.Authority” system service through a DBusProxy on my application. I have never interacted with DBus before, but I believe to be in the right path for what I actually need to do: prompt the user for elevating privileges (typing in their “sudo” password on a modal) and granting the application permissions to execute commands for interacting with dkms
in the background.
Here is the current code in my application.ts
file:
import Adw from "gi://Adw";
import Gio from "gi://Gio";
import GLib from "gi://GLib";
import GObject from "gi://GObject";
import Gst from "gi://Gst";
import Gtk from "gi://Gtk?version=4.0";
import { Window } from "./window.js";
const orgFreedesktopPolicyKit1AuthorityI = `
<node>
<interface name="org.freedesktop.PolicyKit1.Authority">
<method name="EnumerateActions">
<arg type="s" direction="in" name="locale"/>
<arg type="a(ssssssuuua{ss})" direction="out" name="action_descriptions"/>
</method>
</interface>
</node>`;
export class Application extends Adw.Application {
private window?: Window;
static {
GObject.registerClass(this);
}
constructor() {
super({
application_id: pkg.name,
resource_base_path: "/app/tarcisiosurdi/XPDA/",
flags: Gio.ApplicationFlags.DEFAULT_FLAGS,
});
GLib.set_application_name(_("Xbox Peripherals Driver Assistant"));
GLib.setenv("PULSE_PROP_media.role", "production", true);
GLib.setenv("PULSE_PROP_application.icon_name", pkg.name, true);
}
private initAppMenu(): void {
const aboutAction = new Gio.SimpleAction({ name: "about" });
aboutAction.connect("activate", this.showAbout.bind(this));
this.add_action(aboutAction);
const quitAction = new Gio.SimpleAction({ name: "quit" });
quitAction.connect("activate", () => {
if (this.window) {
this.window.close();
}
});
this.add_action(quitAction);
this.set_accels_for_action("app.quit", ["<Primary>q"]);
this.set_accels_for_action("win.show-help-overlay", [
"<Primary>question",
]);
}
public vfunc_startup(): void {
super.vfunc_startup();
log("XPDA (%s)".format(pkg.name));
log("Version: %s".format(pkg.version));
Gst.init(null);
this.initAppMenu();
this.enumerateActions().catch((e) => log(e));
}
public vfunc_activate(): void {
if (!this.window) {
this.window = new Window({ application: this });
if (pkg.name.endsWith("Devel")) this.window.add_css_class("devel");
}
this.window.present();
}
private showAbout(): void {
let appName = GLib.get_application_name();
if (!appName) appName = _("XPDA");
const aboutDialog = new Adw.AboutDialog({
artists: [],
developers: ["Tarcísio Surdi <tarcisio.surdi@pm.me>"],
/* Translators: Replace "translator-credits" with your names, one name per line */
translator_credits: _("translator-credits"),
application_name: appName,
license_type: Gtk.License.AGPL_3_0,
application_icon: pkg.name,
version: pkg.version,
website: "https://github.com/TarsiSurdi/xpda",
issue_url: "https://github.com/TarsiSurdi/xpda/issues",
copyright: "Copyright 2024 Tarcísio Surdi",
});
aboutDialog.present(this.window);
}
private async enumerateActions() {
const AuthProxy = Gio.DBusProxy.makeProxyWrapper(
orgFreedesktopPolicyKit1AuthorityI
);
let proxy = null;
new AuthProxy(
Gio.DBus.system,
"org.freedesktop.PolicyKit1.Authority",
"org/freedesktop/PolicyKit1/Authority",
(sourceObj: Gio.DBusProxy, error: Gio.DBusError) => {
// If @error is not `null` it will be an Error object indicating the
// failure. @proxy will be `null` in this case.
if (error !== null) {
log(error);
return;
}
// At this point the proxy is initialized and you can start calling
// functions, using properties and so on.
proxy = sourceObj;
proxy.call(
"EnumerateActions",
new GLib.Variant("s", ""),
Gio.DBusCallFlags.NONE,
-1,
null
);
},
// Optional Gio.Cancellable object. Pass `null` if you need to pass flags.
null,
// Optional flags passed to the Gio.DBusProxy constructor
Gio.DBusProxyFlags.NONE
);
}
}
When trying this code out, I get the following error: JS LOG: Gio.IOErrorEnum: Could not connect: No such file or directory
. What am I doing wrong here? I believe the issue is around the values I’m providing as bus_name, object_path or interface_name because of the “404” error, but I can’t determine which of these arguments is wrong…
Also, I’m calling EnumerateActions
just because it seems to be a simple method for debugging my app’s communication with DBus. I believe once I have established a successful connection that I would have to use the CheckAuthorization
method and try to execute things with pkexec
for what I need to do? Are there any examples out there trying to do what I need?