Enable Gnome Extensions without session restart

Installing Gnome extensions comes, in my understanding, with to flavors in Gnome40/Fedora 34:

  • (1) Using GNOME Shell integration by Yuri Konotopov : Choose yout favorite extension and toggle the ON/OFF button

  • (2) Install it manually in ~/.local/share/gnome-shell/extensions/ and then :

    • Either use dconf/gsettings with enabled-extensions key to the ones we want
    • Or use gnome-extensions enable <extension uuid>

But only (1) does the extensions to get enabled, magically, WITHOUT restarting the session whereas (2) needs it.

How can I install and enable gnom extensions all in command line within a bash script without having to restart my gnome session ?

Thanks

2 Likes

You can’t install an extension from a file and have it immediately loaded.

If you know the UUID and it’s distributed from extensions.gnome.org, you can ask GNOME Shell to install it by calling the DBus method at org.gnome.Shell.Extensions.installRemoteExtension() which takes the UUID as it’s only argument.

@ andyholmes Thank you for your reply !
I’am quite illiterate regarding the Dbus syntax.

Let’s say I would like to install and enable extension UUID 1319 (yes, GSConnect which BTW is awesome), would you be able to expand your answer with a the full syntax so as to ask GNOME Shell to install it ?

To get it straight I would need to get the same result as toggling ON/OFF GNOME Shell integration’s button:

  • download the extension file
  • run $ gnome-extensions install <UUID>
  • run your DBus command...

Well, like I said you can’t install an extension from a file and have it immediately loaded, even if you download the file from extensions.gnome.org. You have to ask GNOME Shell to both download and install the extension.

An example might be:

gdbus call --session \
           --dest org.gnome.Shell.Extensions \
           --object-path /org/gnome/Shell/Extensions \
           --method org.gnome.Shell.Extensions.InstallRemoteExtension \
           "gsconnect@andyholmes.github.io"

Note that the UUID is not the number from the website, but the extension’s UUID.

Even using the browser extension, it’s the chrome-gnome-shell connector that performs all the magic, and that’s a Python script you can read to see how it does it.

(But the answer is exactly as @andyholmes said, using the InstallRemoteExtension dbus call.) Selected portions of the source:

class ChromeGNOMEShell(Gio.Application):
    def __init__(self, run_as_service):
        Gio.Application.__init__(
            self,
            application_id='org.gnome.ChromeGnomeShell',
            flags=Gio.ApplicationFlags.IS_SERVICE if run_as_service
            else Gio.ApplicationFlags.IS_LAUNCHER | Gio.ApplicationFlags.HANDLES_OPEN
        )
        if not run_as_service:
            self.shell_proxy = Gio.DBusProxy.new_sync(self.get_dbus_connection(),
                                                      Gio.DBusProxyFlags.NONE,
                                                      None,
                                                      'org.gnome.Shell',
                                                      '/org/gnome/Shell',
                                                      'org.gnome.Shell.Extensions',
                                                      None)


    def dbus_call_response(self, method, parameters, result_property):
        try:
            result = self.shell_proxy.call_sync(method,
                                                parameters,
                                                Gio.DBusCallFlags.NONE,
                                                -1,
                                                None)

            self.send_message({'success': True, result_property: result.unpack()[0]})
        except GLib.GError as e:
            self.send_error(e.message)
[...]
if request['execute'] == 'installExtension':
            self.dbus_call_response(
                "InstallRemoteExtension",
                GLib.Variant.new_tuple(GLib.Variant.new_string(request['uuid'])),
                "status"
            )
2 Likes

@andyholmes : Thanks for the reply.
I’ve tried almost successfully your command. Is there away , when invoking InstallRemoteExtension to get around the dialog box Install Extension - Download and Install <extension>
And to have thus the extension downloaded, installed, and then fully activated within a shell script without human interaction ?

1 Like

There is no way to do that, that I know of. I think it would probably be considered a security risk to be able to do that.

2 Likes

In hindsight your absolutely right about user security @andyholmes :
The user should be aware of extensions which are from third parties and not as integrated within Gnome as “Applications Menu”, “Places Status Indicator” or “Windows List” are.

But that’s the situation in this use case here. Within a script extensions can be downloaded, installed, and then fully activated , it just required to restart the user session. And after re-login , extensions are fully operational without user consent through a GUI generated window.
(In my case , I do launch the script, however)

Yes, that’s true. It’s a bit of security theatre since you can work around it the way you describe. I’m just not sure there’s a way to instantly apply an extension the way you want.

@andyholmes : I might have an idea. (Let’s put security aside here).
The purpose of the script is to load a custom user environment atop a fresh Fedora Live USB installation.

In some cases during the script’s process a session restart is mandatory after installing :

  • rpms like openssh and others not included in Fedora Live Workstation
  • some Gnome extensions - (i.e gsconnect , even with InstallRemoteExtension or on/off toggle needs a session restart ).
  • and so on

In itself I’ll be ok that a session restart would be required at the end of the script . I’d like the restart to be as smooth as possible however.
I haven’t found yet a way to include it in my script commands to activate ‘automatic login’ for liveuser (default user in Fedora Live). This way when each piece is installed (rpms, extensions, gsettings, tweaks,…) a session restart would activate smoothly all the new custom user environment.

Any idea how ?

Sorry, I don’t really have any experience in the area of session management or live USB distributions. I’d guess if this was more of a Fedora question, ask.fedoraproject.org might be a better place to find someone who knows about that stuff :slight_smile:

This is where those of us still running under X11 get to be smug — I can hit Alt+F2 and type rEnter to restart the Shell running on my Xorg-atop-Nvidia-drivers desktop whenever I please. (Which does activate any newly hand-installed and/or upgraded extensions, in the process.)

The non-relaunchability of the Shell under Wayland prevents the same thing from being done without a logout there, unfortunately, so the process becomes necessarily more disruptive.

1 Like

Obviously I don’t know the details of your use case, so this may or may not be even remotely workable, but just in the spirit of thinking outside the hollow cardboard receptacle… does it have to be a stock live USB, or can it be a pre-customized one? And backing up a bit, because it would inform the answer to that previous question: Are you talking about an individually (and/or interactively) customized environment each time, or is it the same customizations being applied each time it’s used?

The latter, in particular, would probably be far easier to achieve as a pre-configured liveUSB distribution that already had the customizations pre-applied onto it, something those filesystems/installers are much more conducive to. Any customizations you please, really, could be (in Microsoft’s terminology) “slipstreamed” atop the original live distribution and disseminated already ready already.

Yeah, the problem there is that automatic login is already enabled for the liveuser. But it would defeat the entire purpose of having a “Logout” option if the user were immediately logged back in again, so even in an auto-login situation “Logout” takes you to the greeter — as it should, IMHO, even though it unfortunately makes things difficult for your particular needs.

I did some poking around at the possible options you might have, but unfortunately (though not unexpectedly) came up pretty much empty. loginctl contains plenty of commands for ending sessions, as well as for activating and deactivating them, but (predictably) nothing for creating sessions. And while the org.freedesktop.login1(5) man page does list some DBus interfaces for initiating sessions, it accompanies them with this rather dire admonishment about even considering using them:

   CreateSession() and ReleaseSession() may be used to open or close login
   sessions. These calls should never be invoked directly by clients.
   Creating/closing sessions is exclusively the job of PAM and its
   pam_systemd(8) module.

I was even going to suggest that you might be better off triggering a reboot, rather than a logout / login cycle, since after reboot the existing auto-login would again be triggered… but then I remembered, right, liveUSB. Rebooting would wipe out your customizations and you’d be right back where you started. Another point in favor of pre-applying them to the base filesystem itself, instead. (If at all feasible.) Then you don’t have to re-do the customization each time the live image boots up.

Thank’s for your insights @ FeRDNYC
In fact I would like very much to take the stock Fedora LiveUSB and to customize it through start-up scripts and/or kickstart files. The livecd-tools seem to be perfect and powerful tools for it, namely livecd-iso-to-disk.sh and especially editliveos .
Sadly those tools, while quite well documented, do have their unexpected obstacles for a fresh linux enthousiast like me. I’ve been using them for a couple of years now, and and especially editliveos is rather elusive to me…