[gnome-shell] dbusServices/extensions: Take over prefs dialog from app



commit 34e85342d8d5340023ccb03a17a179c2d968f2d5
Author: Florian Müllner <fmuellner gnome org>
Date:   Wed Mar 4 05:05:08 2020 +0100

    dbusServices/extensions: Take over prefs dialog from app
    
    As outlined earlier, in order to turn the Extensions app into a properly
    sandboxed application, we need to split out the extension prefs dialog
    and move it elsewhere.
    
    With "elsewhere" being the new Extensions D-Bus service, effectively
    turning it into a shell extensions portal.
    
    https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1106

 js/dbusServices/extensions/css/application.css     |   2 +
 js/dbusServices/extensions/extensionsService.js    | 142 ++++++++++++++++++++-
 js/dbusServices/extensions/main.js                 |   9 ++
 .../extensions}/ui/extension-prefs-dialog.ui       |   0
 .../org.gnome.Shell.Extensions.src.gresource.xml   |   6 +
 js/extensionPrefs/data/css/application.css         |   3 -
 .../data/org.gnome.Extensions.data.gresource.xml   |   1 -
 js/extensionPrefs/js/main.js                       | 127 +-----------------
 js/ui/shellDBus.js                                 |  21 +--
 po/POTFILES.in                                     |   2 +-
 10 files changed, 174 insertions(+), 139 deletions(-)
---
diff --git a/js/dbusServices/extensions/css/application.css b/js/dbusServices/extensions/css/application.css
new file mode 100644
index 0000000000..06914ea3c1
--- /dev/null
+++ b/js/dbusServices/extensions/css/application.css
@@ -0,0 +1,2 @@
+.expander-frame > * { border-top-width: 0; }
+.expander-toolbar { border: 0 solid @borders; border-top-width: 1px; }
diff --git a/js/dbusServices/extensions/extensionsService.js b/js/dbusServices/extensions/extensionsService.js
index 9ea07df45c..4823738469 100644
--- a/js/dbusServices/extensions/extensionsService.js
+++ b/js/dbusServices/extensions/extensionsService.js
@@ -1,7 +1,9 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 /* exported ExtensionsService */
 
-const { Gio, GLib } = imports.gi;
+const { Gdk, Gio, GLib, GObject, Gtk } = imports.gi;
+
+const ExtensionUtils = imports.misc.extensionUtils;
 
 const { loadInterfaceXML } = imports.misc.fileUtils;
 const { ServiceImplementation } = imports.dbusService;
@@ -108,10 +110,25 @@ var ExtensionsService = class extends ServiceImplementation {
     }
 
     OpenExtensionPrefsAsync(params, invocation) {
-        this._proxy.OpenExtensionPrefsRemote(...params, (res, error) => {
+        const [uuid, parentWindow_, options] = params;
+
+        this._proxy.GetExtensionInfoRemote(uuid, (res, error) => {
             if (this._handleError(invocation, error))
                 return;
 
+            const [serialized] = res;
+            const extension = ExtensionUtils.deserializeExtension(serialized);
+
+            const window = new ExtensionPrefsDialog(extension);
+
+            if (options.modal)
+                window.modal = options.modal.get_boolean();
+
+            window.connect('destroy', () => this.release());
+            this.hold();
+
+            window.show();
+
             invocation.return_value(null);
         });
     }
@@ -125,3 +142,124 @@ var ExtensionsService = class extends ServiceImplementation {
         });
     }
 };
+
+var ExtensionPrefsDialog = GObject.registerClass({
+    GTypeName: 'ExtensionPrefsDialog',
+    Template: 'resource:///org/gnome/Shell/Extensions/ui/extension-prefs-dialog.ui',
+    InternalChildren: [
+        'headerBar',
+        'stack',
+        'expander',
+        'expanderArrow',
+        'revealer',
+        'errorView',
+    ],
+}, class ExtensionPrefsDialog extends Gtk.Window {
+    _init(extension) {
+        super._init();
+
+        this._uuid = extension.uuid;
+        this._url = extension.metadata.url || '';
+
+        this._headerBar.title = extension.metadata.name;
+
+        this._actionGroup = new Gio.SimpleActionGroup();
+        this.insert_action_group('win', this._actionGroup);
+
+        this._initActions();
+        this._addCustomStylesheet();
+
+        this._gesture = new Gtk.GestureMultiPress({
+            widget: this._expander,
+            button: 0,
+            exclusive: true,
+        });
+
+        this._gesture.connect('released', (gesture, nPress) => {
+            if (nPress === 1)
+                this._revealer.reveal_child = !this._revealer.reveal_child;
+        });
+
+        this._revealer.connect('notify::reveal-child', () => {
+            this._expanderArrow.icon_name = this._revealer.reveal_child
+                ? 'pan-down-symbolic'
+                : 'pan-end-symbolic';
+        });
+
+        try {
+            ExtensionUtils.installImporter(extension);
+
+            // give extension prefs access to their own extension object
+            ExtensionUtils.getCurrentExtension = () => extension;
+
+            const prefsModule = extension.imports.prefs;
+            prefsModule.init(extension.metadata);
+
+            const widget = prefsModule.buildPrefsWidget();
+            this._stack.add(widget);
+            this._stack.visible_child = widget;
+        } catch (e) {
+            this._setError(e);
+        }
+    }
+
+    _setError(exc) {
+        this._errorView.buffer.text = `${exc}\n\nStack trace:\n`;
+        // Indent stack trace.
+        this._errorView.buffer.text +=
+            exc.stack.split('\n').map(line => `  ${line}`).join('\n');
+
+        // markdown for pasting in gitlab issues
+        let lines = [
+            `The settings of extension ${this._uuid} had an error:`,
+            '```',
+            `${exc}`,
+            '```',
+            '',
+            'Stack trace:',
+            '```',
+            exc.stack.replace(/\n$/, ''), // stack without trailing newline
+            '```',
+            '',
+        ];
+        this._errorMarkdown = lines.join('\n');
+        this._actionGroup.lookup('copy-error').enabled = true;
+    }
+
+    _initActions() {
+        let action;
+
+        action = new Gio.SimpleAction({
+            name: 'copy-error',
+            enabled: false,
+        });
+        action.connect('activate', () => {
+            const clipboard = Gtk.Clipboard.get_default(this.get_display());
+            clipboard.set_text(this._errorMarkdown, -1);
+        });
+        this._actionGroup.add_action(action);
+
+        action = new Gio.SimpleAction({
+            name: 'show-url',
+            enabled: this._url !== '',
+        });
+        action.connect('activate', () => {
+            Gio.AppInfo.launch_default_for_uri(this._url,
+                this.get_display().get_app_launch_context());
+        });
+        this._actionGroup.add_action(action);
+    }
+
+    _addCustomStylesheet() {
+        let provider = new Gtk.CssProvider();
+        let uri = 'resource:///org/gnome/Shell/Extensions/css/application.css';
+        try {
+            provider.load_from_file(Gio.File.new_for_uri(uri));
+        } catch (e) {
+            logError(e, 'Failed to add application style');
+        }
+        Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
+            provider,
+            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
+    }
+});
diff --git a/js/dbusServices/extensions/main.js b/js/dbusServices/extensions/main.js
index 8f139a64f4..9cc4bc5e33 100644
--- a/js/dbusServices/extensions/main.js
+++ b/js/dbusServices/extensions/main.js
@@ -1,9 +1,18 @@
 /* exported main */
 
+imports.gi.versions.Gdk = '3.0';
+imports.gi.versions.Gtk = '3.0';
+
+const { Gtk } = imports.gi;
+const pkg = imports.package;
+
 const { DBusService } = imports.dbusService;
 const { ExtensionsService } = imports.extensionsService;
 
 function main() {
+    Gtk.init(null);
+    pkg.initFormat();
+
     const service = new DBusService(
         'org.gnome.Shell.Extensions',
         new ExtensionsService());
diff --git a/js/extensionPrefs/data/ui/extension-prefs-dialog.ui 
b/js/dbusServices/extensions/ui/extension-prefs-dialog.ui
similarity index 100%
rename from js/extensionPrefs/data/ui/extension-prefs-dialog.ui
rename to js/dbusServices/extensions/ui/extension-prefs-dialog.ui
diff --git a/js/dbusServices/org.gnome.Shell.Extensions.src.gresource.xml 
b/js/dbusServices/org.gnome.Shell.Extensions.src.gresource.xml
index 7bbcdab117..7436f2e890 100644
--- a/js/dbusServices/org.gnome.Shell.Extensions.src.gresource.xml
+++ b/js/dbusServices/org.gnome.Shell.Extensions.src.gresource.xml
@@ -6,6 +6,12 @@
     <file>dbusService.js</file>
 
     <file>misc/config.js</file>
+    <file>misc/extensionUtils.js</file>
     <file>misc/fileUtils.js</file>
   </gresource>
+
+  <gresource prefix="/org/gnome/Shell/Extensions">
+    <file>css/application.css</file>
+    <file>ui/extension-prefs-dialog.ui</file>
+  </gresource>
 </gresources>
diff --git a/js/extensionPrefs/data/css/application.css b/js/extensionPrefs/data/css/application.css
index 5641c5d232..37105d0819 100644
--- a/js/extensionPrefs/data/css/application.css
+++ b/js/extensionPrefs/data/css/application.css
@@ -9,6 +9,3 @@
 }
 
 image.warning { color: @warning_color; }
-
-.expander-frame > * { border-top-width: 0; }
-.expander-toolbar { border: 0 solid @borders; border-top-width: 1px; }
diff --git a/js/extensionPrefs/data/org.gnome.Extensions.data.gresource.xml 
b/js/extensionPrefs/data/org.gnome.Extensions.data.gresource.xml
index de65e08233..659c03ffc8 100644
--- a/js/extensionPrefs/data/org.gnome.Extensions.data.gresource.xml
+++ b/js/extensionPrefs/data/org.gnome.Extensions.data.gresource.xml
@@ -5,7 +5,6 @@
 
     <file>dbus-interfaces/org.gnome.Shell.Extensions.xml</file>
 
-    <file>ui/extension-prefs-dialog.ui</file>
     <file>ui/extension-row.ui</file>
     <file>ui/extensions-window.ui</file>
   </gresource>
diff --git a/js/extensionPrefs/js/main.js b/js/extensionPrefs/js/main.js
index b96319c87d..fd76051578 100644
--- a/js/extensionPrefs/js/main.js
+++ b/js/extensionPrefs/js/main.js
@@ -85,7 +85,6 @@ var ExtensionsWindow = GObject.registerClass({
     _init(params) {
         super._init(params);
 
-        this._prefsDialog = null;
         this._updatesCheckId = 0;
 
         this._mainBox.set_focus_vadjustment(this._scrolledWindow.vadjustment);
@@ -152,16 +151,9 @@ var ExtensionsWindow = GObject.registerClass({
     }
 
     openPrefs(uuid) {
-        if (this._prefsDialog)
-            return;
-
-        let row = this._findExtensionRow(uuid);
-        this._prefsDialog = new ExtensionPrefsDialog(row);
-        this._prefsDialog.set({ transient_for: this, modal: true });
-
-        this._prefsDialog.connect('destroy', () => (this._prefsDialog = null));
-
-        this._prefsDialog.show();
+        this._shellProxy.OpenExtensionPrefsRemote(uuid,
+            '',
+            { modal: new GLib.Variant('b', true) });
     }
 
     _showAbout() {
@@ -467,119 +459,6 @@ var ExtensionRow = GObject.registerClass({
     _canToggle() {
         return this._extension.canChange;
     }
-
-    get prefsModule() {
-        // give extension prefs access to their own extension object
-        ExtensionUtils.getCurrentExtension = () => this._extension;
-
-        if (!this._prefsModule) {
-            ExtensionUtils.installImporter(this._extension);
-
-            this._prefsModule = this._extension.imports.prefs;
-            this._prefsModule.init(this._extension.metadata);
-        }
-
-        return this._prefsModule;
-    }
-});
-
-var ExtensionPrefsDialog = GObject.registerClass({
-    GTypeName: 'ExtensionPrefsDialog',
-    Template: 'resource:///org/gnome/Extensions/ui/extension-prefs-dialog.ui',
-    InternalChildren: [
-        'headerBar',
-        'stack',
-        'expander',
-        'expanderArrow',
-        'revealer',
-        'errorView',
-    ],
-}, class ExtensionPrefsDialog extends Gtk.Window {
-    _init(extension) {
-        super._init();
-
-        this._uuid = extension.uuid;
-        this._url = extension.url;
-
-        this._headerBar.title = extension.name;
-
-        this._actionGroup = new Gio.SimpleActionGroup();
-        this.insert_action_group('win', this._actionGroup);
-
-        this._initActions();
-
-        this._gesture = new Gtk.GestureMultiPress({
-            widget: this._expander,
-            button: 0,
-            exclusive: true,
-        });
-
-        this._gesture.connect('released', (gesture, nPress) => {
-            if (nPress === 1)
-                this._revealer.reveal_child = !this._revealer.reveal_child;
-        });
-
-        this._revealer.connect('notify::reveal-child', () => {
-            this._expanderArrow.icon_name = this._revealer.reveal_child
-                ? 'pan-down-symbolic'
-                : 'pan-end-symbolic';
-        });
-
-        try {
-            const widget = extension.prefsModule.buildPrefsWidget();
-            this._stack.add(widget);
-            this._stack.visible_child = widget;
-        } catch (e) {
-            this._setError(e);
-        }
-    }
-
-    _setError(exc) {
-        this._errorView.buffer.text = '%s\n\nStack trace:\n'.format(exc);
-        // Indent stack trace.
-        this._errorView.buffer.text +=
-            exc.stack.split('\n').map(line => '  %s'.format(line)).join('\n');
-
-        // markdown for pasting in gitlab issues
-        let lines = [
-            'The settings of extension %s had an error:'.format(this._uuid),
-            '```', // '`' (xgettext throws up on odd number of backticks)
-            exc.toString(),
-            '```', // '`'
-            '',
-            'Stack trace:',
-            '```', // '`'
-            exc.stack.replace(/\n$/, ''), // stack without trailing newline
-            '```', // '`'
-            '',
-        ];
-        this._errorMarkdown = lines.join('\n');
-        this._actionGroup.lookup('copy-error').enabled = true;
-    }
-
-    _initActions() {
-        let action;
-
-        action = new Gio.SimpleAction({
-            name: 'copy-error',
-            enabled: false,
-        });
-        action.connect('activate', () => {
-            const clipboard = Gtk.Clipboard.get_default(this.get_display());
-            clipboard.set_text(this._errorMarkdown, -1);
-        });
-        this._actionGroup.add_action(action);
-
-        action = new Gio.SimpleAction({
-            name: 'show-url',
-            enabled: this._url !== '',
-        });
-        action.connect('activate', () => {
-            Gio.AppInfo.launch_default_for_uri(this._url,
-                this.get_display().get_app_launch_context());
-        });
-        this._actionGroup.add_action(action);
-    }
 });
 
 function initEnvironment() {
diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js
index 983a887123..2b6b2ae964 100644
--- a/js/ui/shellDBus.js
+++ b/js/ui/shellDBus.js
@@ -1,7 +1,7 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 /* exported GnomeShell, ScreenSaverDBus */
 
-const { Gio, GLib, Meta, Shell } = imports.gi;
+const { Gio, GLib, Meta } = imports.gi;
 
 const Config = imports.misc.config;
 const ExtensionDownloader = imports.ui.extensionDownloader;
@@ -315,13 +315,18 @@ var GnomeShellExtensions = class {
         this.OpenExtensionPrefs(uuid, '', {});
     }
 
-    OpenExtensionPrefs(uuid, _parentWindow, _options) {
-        let appSys = Shell.AppSystem.get_default();
-        let app = appSys.lookup_app('org.gnome.Extensions.desktop');
-        let info = app.get_app_info();
-        let timestamp = global.display.get_current_time_roundtrip();
-        info.launch_uris([`extension:///${uuid}`],
-                         global.create_app_launch_context(timestamp, -1));
+    OpenExtensionPrefs(uuid, parentWindow, options) {
+        Gio.DBus.session.call(
+            'org.gnome.Shell.Extensions',
+            '/org/gnome/Shell/Extensions',
+            'org.gnome.Shell.Extensions',
+            'OpenExtensionPrefs',
+            new GLib.Variant('(ssa{sv})', [uuid, parentWindow, options]),
+            null,
+            Gio.DBusCallFlags.NONE,
+            -1,
+            null,
+            (conn, res) => conn.call_finish(res));
     }
 
     ReloadExtension(uuid) {
diff --git a/po/POTFILES.in b/po/POTFILES.in
index ba8a5b13bd..92cdaf5ce4 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -4,10 +4,10 @@ data/50-gnome-shell-system.xml
 data/org.gnome.Shell.desktop.in.in
 data/org.gnome.shell.gschema.xml.in
 data/org.gnome.Shell.PortalHelper.desktop.in.in
+js/dbusServices/extensions/ui/extension-prefs-dialog.ui
 js/extensionPrefs/data/metainfo/org.gnome.Extensions.metainfo.xml.in
 js/extensionPrefs/data/org.gnome.Extensions.desktop.in.in
 js/extensionPrefs/js/main.js
-js/extensionPrefs/data/ui/extension-prefs-dialog.ui
 js/extensionPrefs/data/ui/extension-row.ui
 js/extensionPrefs/data/ui/extensions-window.ui
 js/gdm/authPrompt.js


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