[gnome-shell] dbusServices/extensions: Proxy Extensions API



commit 91b7474d5a7bc711efdbb68c29ad2ae7ef3a8d68
Author: Florian Müllner <fmuellner gnome org>
Date:   Wed Mar 4 04:02:28 2020 +0100

    dbusServices/extensions: Proxy Extensions API
    
    Similar to the previously added org.freedesktop.Notifications proxy,
    this exposes the org.gnome.Shell.Extensions API and forwards any
    request to the real implementation in gnome-shell.
    
    The motivation differs though: We want to be able to package the
    extension app as flatpak and distribute it separately, but the
    extension prefs dialog is hard to impossible to sandbox:
    
     - filenames need translating between host and sandbox, and we
       can only do that in some cases (serializing/deserializing
       extensions), but not others (extension settings that refer
       to files)
    
     - system extensions install their GSettings schemas in the system
       path; the best we can do there is assume a host prefix of /usr
       and set GSETTINGS_SCHEMA_DIR in the flatpak (eeks)
    
     - extensions may rely on additional typelibs that are present on
       the host (for example because gnome-shell itself depends on
       them), but not inside the sandbox - unless we bundle all of
       gnome-shell's dependencies
    
     - if gjs/mozjs differ between host and sandbox, extensions must
       handle different runtimes for the extension and its prefs
    
    And all those issues occur despite a very permissive sandbox (full
    host filesystem access, full dconf access, full org.gnome.Shell
    access (including Eval()!)).
    
    This new service will give us an alternative place for handling
    the preference dialog:
    
     - it runs outside of gnome-shell process, so can open windows
    
     - it runs on the host, so the extension's prefs get to run
       in the same namespace as the extension itself
    
    That is, the service will provide portal-like functionality (albeit
    not using the org.freedesktop.portal.* namespace, as extension
    management is an inherently privileged operation).
    
    https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1106

 js/dbusServices/extensions/extensionsService.js    | 127 +++++++++++++++++++++
 js/dbusServices/extensions/main.js                 |  11 ++
 js/dbusServices/meson.build                        |   1 +
 .../org.gnome.Shell.Extensions.src.gresource.xml   |  11 ++
 4 files changed, 150 insertions(+)
---
diff --git a/js/dbusServices/extensions/extensionsService.js b/js/dbusServices/extensions/extensionsService.js
new file mode 100644
index 0000000000..9ea07df45c
--- /dev/null
+++ b/js/dbusServices/extensions/extensionsService.js
@@ -0,0 +1,127 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+/* exported ExtensionsService */
+
+const { Gio, GLib } = imports.gi;
+
+const { loadInterfaceXML } = imports.misc.fileUtils;
+const { ServiceImplementation } = imports.dbusService;
+
+const ExtensionsIface = loadInterfaceXML('org.gnome.Shell.Extensions');
+const ExtensionsProxy = Gio.DBusProxy.makeProxyWrapper(ExtensionsIface);
+
+var ExtensionsService = class extends ServiceImplementation {
+    constructor() {
+        super(ExtensionsIface, '/org/gnome/Shell/Extensions');
+
+        this._proxy = new ExtensionsProxy(Gio.DBus.session,
+            'org.gnome.Shell', '/org/gnome/Shell');
+
+        this._proxy.connectSignal('ExtensionStateChanged',
+            (proxy, sender, params) => {
+                this._dbusImpl.emit_signal('ExtensionStateChanged',
+                    new GLib.Variant('(sa{sv})', params));
+            });
+
+        this._proxy.connect('g-properties-changed', () => {
+            this._dbusImpl.emit_property_changed('UserExtensionsEnabled',
+                new GLib.Variant('b', this._proxy.UserExtensionsEnabled));
+        });
+    }
+
+    get ShellVersion() {
+        return this._proxy.ShellVersion;
+    }
+
+    get UserExtensionsEnabled() {
+        return this._proxy.UserExtensionsEnabled;
+    }
+
+    set UserExtensionsEnabled(enable) {
+        this._proxy.UserExtensionsEnabled = enable;
+    }
+
+    ListExtensionsAsync(params, invocation) {
+        this._proxy.ListExtensionsRemote(...params, (res, error) => {
+            if (this._handleError(invocation, error))
+                return;
+
+            invocation.return_value(new GLib.Variant('(a{sa{sv}})', res));
+        });
+    }
+
+    GetExtensionInfoAsync(params, invocation) {
+        this._proxy.GetExtensionInfoRemote(...params, (res, error) => {
+            if (this._handleError(invocation, error))
+                return;
+
+            invocation.return_value(new GLib.Variant('(a{sv})', res));
+        });
+    }
+
+    GetExtensionErrorsAsync(params, invocation) {
+        this._proxy.GetExtensionErrorsRemote(...params, (res, error) => {
+            if (this._handleError(invocation, error))
+                return;
+
+            invocation.return_value(new GLib.Variant('(as)', res));
+        });
+    }
+
+    InstallRemoteExtensionAsync(params, invocation) {
+        this._proxy.InstallRemoteExtensionRemote(...params, (res, error) => {
+            if (this._handleError(invocation, error))
+                return;
+
+            invocation.return_value(new GLib.Variant('(s)', res));
+        });
+    }
+
+    UninstallExtensionAsync(params, invocation) {
+        this._proxy.UninstallExtensionRemote(...params, (res, error) => {
+            if (this._handleError(invocation, error))
+                return;
+
+            invocation.return_value(new GLib.Variant('(b)', res));
+        });
+    }
+
+    EnableExtensionAsync(params, invocation) {
+        this._proxy.EnableExtensionRemote(...params, (res, error) => {
+            if (this._handleError(invocation, error))
+                return;
+
+            invocation.return_value(new GLib.Variant('(b)', res));
+        });
+    }
+
+    DisableExtensionAsync(params, invocation) {
+        this._proxy.DisableExtensionRemote(...params, (res, error) => {
+            if (this._handleError(invocation, error))
+                return;
+
+            invocation.return_value(new GLib.Variant('(b)', res));
+        });
+    }
+
+    LaunchExtensionPrefsAsync([uuid], invocation) {
+        this.OpenExtensionPrefsAsync([uuid, '', {}], invocation);
+    }
+
+    OpenExtensionPrefsAsync(params, invocation) {
+        this._proxy.OpenExtensionPrefsRemote(...params, (res, error) => {
+            if (this._handleError(invocation, error))
+                return;
+
+            invocation.return_value(null);
+        });
+    }
+
+    CheckForUpdatesAsync(params, invocation) {
+        this._proxy.CheckForUpdatesRemote(...params, (res, error) => {
+            if (this._handleError(invocation, error))
+                return;
+
+            invocation.return_value(null);
+        });
+    }
+};
diff --git a/js/dbusServices/extensions/main.js b/js/dbusServices/extensions/main.js
new file mode 100644
index 0000000000..8f139a64f4
--- /dev/null
+++ b/js/dbusServices/extensions/main.js
@@ -0,0 +1,11 @@
+/* exported main */
+
+const { DBusService } = imports.dbusService;
+const { ExtensionsService } = imports.extensionsService;
+
+function main() {
+    const service = new DBusService(
+        'org.gnome.Shell.Extensions',
+        new ExtensionsService());
+    service.run();
+}
diff --git a/js/dbusServices/meson.build b/js/dbusServices/meson.build
index 2cca6544fa..c749f45dcb 100644
--- a/js/dbusServices/meson.build
+++ b/js/dbusServices/meson.build
@@ -4,6 +4,7 @@ launcherconf.set('prefix', prefix)
 launcherconf.set('libdir', libdir)
 
 dbus_services = {
+  'org.gnome.Shell.Extensions': 'extensions',
   'org.gnome.Shell.Notifications': 'notifications',
 }
 
diff --git a/js/dbusServices/org.gnome.Shell.Extensions.src.gresource.xml 
b/js/dbusServices/org.gnome.Shell.Extensions.src.gresource.xml
new file mode 100644
index 0000000000..7bbcdab117
--- /dev/null
+++ b/js/dbusServices/org.gnome.Shell.Extensions.src.gresource.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/org/gnome/Shell/Extensions/js">
+    <file>main.js</file>
+    <file>extensionsService.js</file>
+    <file>dbusService.js</file>
+
+    <file>misc/config.js</file>
+    <file>misc/fileUtils.js</file>
+  </gresource>
+</gresources>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]