When the extension system is loaded, create the
gnome-shell-disable-extensions file in the users runtime directory. This
file is automatically removed 60s later. The sole purpose of this file
is to be consumed by the systemd units. If the file exists, the systemd
units will disable extensions when the gnome-shell fails.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/858
Since disabling an extension will lead to disabling and re-enabling all
following extensions in the list, always disable multiple extensions by
looping through the list in reverse order.
This lowers the execution time of the event handlers quite a bit if many
extensions are installed.
Thanks to Philippe Troin for identifying the problem and proposing the
initial patch to change the extension order when reloading.
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/177https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/96
Only push uuids of newly enabled extensions to the `_extensionOrder`
array if enabling them was successful.
Otherwise, since `_callExtensionDisable()` doesn't remove uuids that
weren't successfully enabled from the array, those extensions get added
to the array multiple times when they're disabled and enabled.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/96
It's currently possible to circumvent the `sessionMode.allowExtensions`
property: For already enabled extensions one can call reloadExtension
via DBus, for new extensions it's possible by adding the extension to
the enabled-extensions gsettings key and setting the
disable-extension-version-validation key (which triggers a reload of
`this._enabledExtensions`) and then calling reloadExtension via DBus.
So to enforce `allowExtensions` while still allowing to update
extensions and keeping the extensionSystem synced with various gsettings
keys, replace the checks for `this._enabled` with simple checks for
`Main.sessionMode.allowExtensions` inside `_callExtensionInit()` and
`_callExtensionEnable()`.
The remaining checks for `this._enabled` are only small optimizations to
prevent running code on irrelevant sessionMode updates.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/96
Right now we're only handling added sessionMode extensions correctly on
sessionMode updates, also handle the other case and disable removed
sessionMode extensions on sessionMode updates.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/96
Instead of only logging a message that loading the extension stylesheet
failed and silently returning we should use `logExtensionError` for that
instead. This also sets the extension state to ERROR and makes sure we
don't try to enable it again.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/96
If the extension doesn't exist in the `this._extensions` Map, we'd try
to access `extension.dir` on undefined/null. So set the `dir` variable
after checking if `extension` is defined.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/96
Extensions might emit JS errors explicitly or implicitly, however GNOME
Shell doesn't present any stack trace for those making them quite hard
to debug.
Make this easier by logging errors with logError() whichs includes the
stack dump.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/700
While we aren't using those destructured variables, they are still useful
to document the meaning of those elements. We don't want eslint to keep
warning about them though, so mark them accordingly.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/627
Trying to disable an extension that is enabled by the session mode
currently has no effect, which is clearly confusing. We could update
the various extension UIs to reflect that via sensitivity, but being
unable to configure extensions based on which session the user picked
at login isn't obvious either.
So instead, add a 'disabled-extensions' gsettings key to list extensions
that should not be enabled which takes precedence over 'enabled-extensions'
and can be used to disable session mode extensions.
https://bugzilla.gnome.org/show_bug.cgi?id=789852
Now that extension loading and the extensions map are no longer shared
between the gnome-shell and gnome-shell-extension-prefs processes, we
can move both into the ExtensionManager which makes much more sense
conceptually.
https://bugzilla.gnome.org/show_bug.cgi?id=789852
Whether or not an extension can be enabled/disabled depends on various
factors: Whether the extension is in error state, whether user extensions
are disabled and whether the underlying GSettings keys are writable.
This is complex enough to share the logic, so add it to the extension
properties that are exposed over D-Bus.
https://bugzilla.gnome.org/show_bug.cgi?id=789852
The existing 'ExtensionStatusChanged' signal has a fixed set of parameters,
which means we cannot add additional state without an API break. Deprecate
it in favor of a new 'ExtensionStateChanged' signal which addresses this
issue by taking the full serialized extension as parameter.
https://bugzilla.gnome.org/show_bug.cgi?id=789852
Extensions are currently enabled or disabled by directly changing the
list in the 'enabled-extensions' GSettings key. As we will soon add
an overriding 'disabled-extensions' key as well, it makes sense to
offer explicit API for enabling/disabling to avoid duplicating the
logic.
For the corresponding D-Bus API, the methods were even mentioned in
the GSettings schema, albeit unimplemented until now.
https://bugzilla.gnome.org/show_bug.cgi?id=789852
While public methods to enable/disable extensions make sense for an
extension manager, the existing ones are only used internally. Make
them private and rename them, so that we can re-use the current
names for more useful public methods.
https://bugzilla.gnome.org/show_bug.cgi?id=789852
The extension system started out as a set of simple functions, but
gained more state later, and even some hacks to emit signals without
having an object to emit them on.
There is no good reason for that weirdness, so rather than imitating an
object, wrap the existing system into a real ExtensionManager object.
https://bugzilla.gnome.org/show_bug.cgi?id=789852
It makes sense to keep extension-related enums in the same module instead
of spreading them between ExtensionSystem and ExtensionUtils.
More importantly, this will make the type available to the extensions-prefs
tool (which runs in a different process and therefore only has access to
a limited set of modules).
https://bugzilla.gnome.org/show_bug.cgi?id=789852
We are currently inconsistent with whether or not to put a space
after catch clauses. While the predominant style is to omit it,
that's inconsistent with the style we use for any other statement.
There's not really a good reason to stick with it, so switch to
the style gjs/eslint default to.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/607
Converting a variable to a particular type can be done explicitly (with
functions like Number() or toString()) or implicitly by relying on type
coercion (like concatenating a variable to the empty string to force
a string, or multiplying it with 1 to force a number).
As those tend to be less readable and clear, they are best avoided. So
replace the cases of string coercion we use with template strings, and
clarify the places that can be confused with number coercion.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/607
We can use that newer method where we don't care about the actual position
of an element inside the array.
(Array.includes() and Array.indexOf() do behave differently in edge cases,
for example in the handling of NaN, but those don't matter to us)
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/152
We must remove the GFile reference from the representing object when an
extension has been unloaded as this won't be used anymore later (e.g. as cached
ref).
We currently assign the stylesheet to an extension whenever the file exists,
regardless of whether it actually loaded successfully or not.
And thus we load an extension that ships a stylesheet even if that file can't
be used.
There is no point in trying to load an extension if its stylesheet wasn't
loaded in the first place, so make sure this happens only on success.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/188
When not using arrow notation with anonymous functions, we use Lang.bind()
to bind `this` to named callbacks. However since ES5, this functionality
is already provided by Function.prototype.bind() - in fact, Lang.bind()
itself uses it when no extra arguments are specified. Just use the built-in
function directly where possible, and use arrow notation in the few places
where we pass additional arguments.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/23
The method currently catches errors that occur when calling the
extension's init() method, but throws itself an error if the
expected extension.js file is missing. The former is pointless
if we expect all callers to handle errors themselves anyway, and
we should avoid the latter if we don't - opt for the second option
and handle a missing extension.js file gracefully.
https://bugzilla.gnome.org/show_bug.cgi?id=781728
While we catch errors that occur when calling init(), enable() or
disable(), the import itself can throw an exception, for instance
if the extension imports an unavailable typelib or tries to draw
in a conflicting library.
https://bugzilla.gnome.org/show_bug.cgi?id=781728
Both reloadExtensions() and enableExtensions() are already expected
to catch extension errors. If they don't, this is the bug that
should be fixed instead of catching unhandled exceptions in the
caller.
This reverts commit ff425d1db7.
https://bugzilla.gnome.org/show_bug.cgi?id=781728
Some extensions out there may fail to reload. When that happens,
we need to catch any exceptions so that we don't leave things in
a broken state that could lead to leaving extensions enabled in
the screen shield.
https://bugzilla.gnome.org/show_bug.cgi?id=781728
When gnome-shell fails to start on login, gnome-session tries to
re-launch it again with all extensions disabled. This is currently
implemented by clearing the list of enabled extensions, which means
the user needs to re-enable their extensions manually again.
To make this process less annoying, add a single 'kill-switch' setting
gnome-session can use without interfering with the user setting.
https://bugzilla.gnome.org/show_bug.cgi?id=778664
Before reenabling all extensions, we update the list of enabled extensions
to catch any changes that happened while extensions were enabled. However
this is currently broken as onEnabledExtensionsChanged() is a nop while
disabled, so just call getEnabledExtensions() directly.
The current code only works for enabled extensions, which means
that extensions that were marked OUT_OF_DATE cannot be enabled
without a restart when disabling the version check.
Fix this by reloading all extensions while making sure to only
enable any extensions when we're supposed to.
https://bugzilla.gnome.org/show_bug.cgi?id=736185
Add a key 'disable-extension-version-validation' key that disables
the validation of extension's claimed to be supported shell version
with the shell version and just load all extensions unconditionally.
https://bugzilla.gnome.org/show_bug.cgi?id=724683
The asynchronous nature of extension loading, session loading, and more,
makes the code racy as to what is initialized first, and hard to debug.
Additionally, since gjs is single-threaded, the only code we're running
in a thread anyway is readdir, which is going to be I/O bound, so the
code here is actually likely to be faster.
Drop this in favor of some good old fashioned synchronous loading.