From c170d6c9564e53ade09974aafbbeaf09d20d97a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Sat, 10 Feb 2024 00:58:27 +0100 Subject: [PATCH] extensionSystem: Support locking down extension installation Currently extensions can only be locked down completely by restricting the `enabled-extensions` key via dconf. This is too restrictive for environments that want to allow users to customize their system with extensions, while still limiting the set of possible extensions. To fill that gap, add a new `allow-extension-installation` setting, which restricts extensions to system extensions when disabled. As the setting is mainly intended for locking down by system administrators, there is no attempt to load/unload extensions on settings changes. Part-of: --- data/org.gnome.shell.gschema.xml.in | 11 +++++++++++ js/misc/dbusErrors.js | 1 + js/ui/extensionDownloader.js | 7 +++++++ js/ui/extensionSystem.js | 10 +++++++--- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/data/org.gnome.shell.gschema.xml.in b/data/org.gnome.shell.gschema.xml.in index f4fa86d01..4ddc6a119 100644 --- a/data/org.gnome.shell.gschema.xml.in +++ b/data/org.gnome.shell.gschema.xml.in @@ -40,6 +40,17 @@ the “enabled-extension” setting. + + true + Allow extension installation + + Allow users to install extensions in their home folder. If disabled, + the InstallRemoteExtension D-Bus method will fail, and extensions + are only loaded from system directories on startup. + It does not affect extensions that are already loaded, so a change + only takes full effect on the next login. + + false Disables the validation of extension version compatibility diff --git a/js/misc/dbusErrors.js b/js/misc/dbusErrors.js index 6f4f80b51..ec726e89c 100644 --- a/js/misc/dbusErrors.js +++ b/js/misc/dbusErrors.js @@ -40,6 +40,7 @@ export const ExtensionError = { DOWNLOAD_FAILED: 1, EXTRACT_FAILED: 2, ENABLE_FAILED: 3, + NOT_ALLOWED: 4, }; export const ExtensionErrors = registerErrorDomain('Extensions', ExtensionError); diff --git a/js/ui/extensionDownloader.js b/js/ui/extensionDownloader.js index 6486bbcad..33f168ce6 100644 --- a/js/ui/extensionDownloader.js +++ b/js/ui/extensionDownloader.js @@ -32,6 +32,13 @@ let _httpSession; * @returns {void} */ export async function installExtension(uuid, invocation) { + if (!global.settings.get_boolean('allow-extension-installation')) { + invocation.return_error_literal( + ExtensionErrors, ExtensionError.NOT_ALLOWED, + 'Extension installation is not allowed'); + return; + } + const params = { uuid, shell_version: Config.PACKAGE_VERSION, diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js index 07be8066c..76ae58ff4 100644 --- a/js/ui/extensionSystem.js +++ b/js/ui/extensionSystem.js @@ -86,8 +86,11 @@ export class ExtensionManager extends Signals.EventEmitter { get updatesSupported() { const appSys = Shell.AppSystem.get_default(); - return (appSys.lookup_app('org.gnome.Extensions.desktop') !== null) || - (appSys.lookup_app('com.mattjakeman.ExtensionManager.desktop') !== null); + const hasUpdatesApp = + appSys.lookup_app('org.gnome.Extensions.desktop') !== null || + appSys.lookup_app('com.mattjakeman.ExtensionManager.desktop') !== null; + const allowed = global.settings.get_boolean('allow-extension-installation'); + return allowed && hasUpdatesApp; } lookup(uuid) { @@ -745,7 +748,8 @@ export class ExtensionManager extends Signals.EventEmitter { let perUserDir = Gio.File.new_for_path(global.userdatadir); - const extensionFiles = [...FileUtils.collectFromDatadirs('extensions', true)]; + const includeUserDir = global.settings.get_boolean('allow-extension-installation'); + const extensionFiles = [...FileUtils.collectFromDatadirs('extensions', includeUserDir)]; const extensionObjects = extensionFiles.map(({dir, info}) => { let fileType = info.get_file_type(); if (fileType !== Gio.FileType.DIRECTORY)