-
Notifications
You must be signed in to change notification settings - Fork 0
/
extension.js
102 lines (82 loc) · 2.99 KB
/
extension.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const { DBusSenderChecker } = imports.misc.util;
const { main } = imports.ui;
// Copied and extended from: https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/misc/introspect.js
const APP_ALLOWLIST = [
'org.freedesktop.impl.portal.desktop.gtk',
'org.freedesktop.impl.portal.desktop.gnome',
'org.gnome.Shell',
];
const DBUS_INTERFACE = `
<node>
<interface name="dev.wxwee.SafeIntrospect">
<method name="GetWindows">
<arg name="windows" direction="out" type="a{ta{sv}}" />
</method>
</interface>
</node>
`;
class SafeIntrospect {
constructor() {
log("Initializing SafeIntrospection extension.");
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(DBUS_INTERFACE, this);
this._initializedChecker = false;
}
enable() {
log("Enabling SafeIntrospection extension.");
this._dbusImpl.export(Gio.DBus.session, '/dev/wxwee/SafeIntrospect');
}
checkInitialized() {
if (this._initializedChecker) {
return true;
}
if (main.introspectService && main.introspectService._senderChecker) {
main.introspectService._senderChecker = new DBusSenderChecker(APP_ALLOWLIST);
this._initializedChecker = true;
}
return this._initializedChecker;
}
async GetWindowsAsync(_params, invocation) {
const isInitialized = this.checkInitialized();
if (!isInitialized) {
invocation.return_gerror(new Error("Unable to initialize Introspect service"));
return;
}
const variant = '(a{ta{sv}})';
Gio.DBus.session.call(
'org.gnome.Shell.Introspect',
'/org/gnome/Shell/Introspect',
'org.gnome.Shell.Introspect',
'GetWindows',
null,
new GLib.VariantType(variant),
Gio.DBusCallFlags.NONE,
-1,
null,
(connection, res) => {
try {
const reply = connection.call_finish(res);
const replyUnpacked = reply.deepUnpack();
for (const [_windowId, windowProperties] of Object.entries(replyUnpacked[0])) {
// Obfuscate the title.
windowProperties['title'] = GLib.Variant.new_string('');
}
invocation.return_value(new GLib.Variant(variant, replyUnpacked));
} catch (e) {
log("Failed after calling Introspect: ", e);
invocation.return_gerror(GLib.Error(Gio.DBusError,
Gio.DBusError.FAILED,
`Failed calling Introspect API: ${e}`));
}
}
);
}
disable() {
log("Disabling SafeIntrospection extension.");
if (this._dbusImpl) this._dbusImpl.unexport();
}
}
function init() {
return new SafeIntrospect();
}