Introduce a new class, EventEmitter, which implements signal
handling for pure JavaScript classes. EventEmitter still
utilizes GJS' addSignalMethods internally.
EventEmitter allows static typechecking to understand the
structure of event-emitting JS classes and makes creating
child classes simpler.
The name 'EventEmitter' mirrors a common name for this pattern
in Node and in JS libraries.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2043>
Start using the new methods to simplify signal cleanup. For now,
focus on replacing existing cleanups; in most cases this means
signals connected in the constructor and disconnected on destroy,
but also other cases with a similarly defined lifetime (say: from
show to hide).
This doesn't change signal connections that only exist for a short
time (say: once), handlers that are connected on-demand (say: the
first time a particular method is called), or connections that
aren't tracked (read: disconnected) at all.
We will eventually replace the latter with connectObject() as
well - especially from actor subclasses - but the changeset is
already big enough as-is :-)
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1953>
We have made good progress on object literals as well, although there
are still a lot that use the old style, given how ubiquitous object
literals are.
But the needed reindentation isn't overly intrusive, as changes are
limited to the object literals themselves (i.e. they don't affect
surrounding code).
And given that object literals account for quite a bit of the remaining
differences between regular and legacy rules, doing the transition now
is still worthwhile.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2200>
It's unfortunate that we cannot fully embrace template strings, but
we aren't limited to "legacy" formatting either; replace the last
remaining places where we still use string concatenation to reduce
the difference between regular and legacy style a bit.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2200>
If the finish function isn't specified, promisify will now try
to use the async name without '_async'/'_begin' suffix (if any)
and '_finish' appended.
Everything except IBus uses a variation of that pattern, so there's
quite a bit of boilerplate we get to remove…
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2174>
All callers have been updated to keep this handle to identify their
own grab.
Also, optionally use the windowing state to determine whether
the grab is suitable for the specific uses. This removes the need
to trying to grab twice in the places where we settle for a keyboard
grab.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2045>
Despite this grab happening in the dialog, we are also interested in
things happening outside of it. Move this grab to happen in the stage
itself, so the changed grab semantics don't make it impossible to
interact with parts of the login screen.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2045>
Ultimately, we want to add support for GDM's new ChoiceList
PAM extension. That extension allows PAM modules to present
a list of choices to the user. Before we can support that
extension, however, we need to have a list control in the
login-screen/unlock screen. This commit adds that control.
For the most part, it's a copy-and-paste of the gdm userlist,
but with less features. It lacks API specific to the users,
lacks the built in timed login indicator, etc. It does feature
a label heading.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1978>
It can happen that we get a problem report and a verification failure at
the same time. For fingerprint, a problem report can result in an
internal verification failure to be queued.
Remove this queued failure again if we got a failure already from GDM
directly.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1821>
At the moment a failure in a background service can lead to the
various verification signals getting disconnected, even though
we still need them for a foreground service.
This commit changes the code to only disconnect when we've run
out of tries.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1821>
At the moment we set the state of the auth prompt to failed any
time the user fails an attempt. But verification is still going
on until the user exhausts all attempts, so that's wrong.
This commit changes it to only set the state to failed when the
user is out of tries.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1821>
At the moment we treat a failure in any service as a signal to stop
tracking users responses to service questions.
This commit makes sure we don't stop waiting for answers if a background
service fails.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1821>
At the moment the timed login feature is implemented in the user list.
If there's no user list, we don't show the indicator anywhere and
don't proceed with timed login.
This commit allows timed login to work when the user list is disabled.
It accomplishes this by putting the timed login indicator on the
auth prompt in that scenario.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1809>
When we got an error, all the other HINT or INFO messages are not useful
anymore and delaying to show them is just a waste of time and may be
even wrong in scenarios with fast authentication devices.
An example are the fingerprint devices, where the user may touch the
sensor repeatedly while we may still show the "touch the sensor" hint
instead of notifying of possible errors.
So, in case we got an error override all the other errors coming from
the same service with lower priority.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1683>
Once the verification has been stopped or has failed all the messages
that are not of error type are just not needed or wrong to show.
For example, in the fingerprint case we may still show the hint to swipe
or touch the device, while the fingerprint PAM service has already been
stopped.
So filter them by adding a new function that adds a null message to the
queue, overriding all the messages that have a lower priority.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1683>
There are cases in which a service may want to override a message with
one coming with higher priority, for example an info or hint message
isn't useful anymore if we've already got an error message.
In the same way when a service has been stopped we don't care anymore
showing its info or hint messages, while it still may be relevant to show
errors.
An example is the fingerprint service that may emit errors quickly while
the hints messages should not be kept around when an error is already
queued or when the service has been stopped.
So, add function that allows to override queued messages based by their
type that follows this policy:
- Messages coming from different services are always preserved in
their original order.
- Messages (from the same service) with a priority equal or higher than
the last queued one are preserved.
- Messages matching completely the last queued are dropped in favor of
this one.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1683>
It can be convenient to get the currently showing message in order to
replace or remove it in case it's not needed anymore.
So simplify the message queue handling by only depending on a single
local variable (_messageQueue) and redefining hasPendingMessages
depending on its content.
Now messages are kept in queue till they are not fully processed and the
first message is always the one currently shown.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1683>
When a fingerprint failure event happens we may also soon receive a
conversation-stopped event with an error message (such as in the case
we hit the MAXRETRIES value), but this is going to be ignored in case we
are too quick in consider the first failure a verification-failed event
because that implies disconnecting from all the events and then ignoring
such signals.
To prevent this, add a small timeout before failing the verification so
that if we get a further event we will process it.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1683>
In the case a service is not available (as it can be in the fingereprint
case when a supported reader is available but has not enrolled prints)
we were trying indefinitely to restart it, however this can lead to
troubles since commit 7a2e629b as when the service conversation was
stopped we had no way to figure out this case and we'd end up to
eventually fail the whole authentication.
However, in such cases the PAM services are expected to return a
PAM_AUTHINFO_UNAVAIL and gdm to handle it, emitting service-unavailable
signal.
So connect to ::service-unavailable and keep track of the unavailable
services so that we can avoid retrying with them.
In case such service is not the foreground one, we can just silently
ignore the error as we did before commit 7a2e629b, without bothering
failing the whole verification.
In case we got a valid error message on service-unavailable, we also
show it, this is normally not happening unless GDM isn't redirecting
here other kind of problems (such as MAXTRIES) which are supposed to
stop the authentication stopping any further retry.
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3734
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1683>
Currently when the foreground service conversation stops we increase the
verification failed count and try to start it again, while if a
background service has been stopped we just ignore it.
This is causing a various number of issues, for example in the case of
the fingerprint authentication service, it is normally configured to die
after a timeout, and we end up never restarting it (while the UI still
keeps showing to the user the message about swipe/touch the device).
So, in such case let's just consider it a "soft" verification failure
that doesn't increase the failures count but will cause us to reset the
UI and try to restart the authentication (and so the affected service).
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1652>
Wiggle may make the error message to be visible for less time so provide
the auth prompt an API to increase the timeout to be used for showing a
message in some cases.
This could be reworked when we'll have a proper asyn wiggle function so
that we could just make the user verifier to "freeze", then await for
the wiggle transition to complete and eventually release the verifier.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1652>
Currently whenever an authentication failure happens we wiggle the
entry, however this may not be related to the service which failed.
For example if the fingerprint authentication failed for whatever reason,
there's no point to wiggle the text input as it's something unrelated to it.
So, only apply the wiggle effect to the entry in case the failure is
coming from the querying service.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1652>
By giving to the AuthPrompt information regarding the source service
name (and so the ability to know whether it's a foreground service) can
give it the ability to behave differently.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1652>
Fingerprint PAM module can have multiple failures during a runtime
and we rely on the pam module configuration for the maximum allowed
retries.
However, while that setting should be always followed, we should never
ignore the login-screen's allowed-failures setting that can provide
a lower value.
So, once we have a fingerprint failure let's count it to increase our
internal fail counter, and when we've reached the limit we can emit a
verification-failed signal to our clients.
As per this we need also to ignore any further 'info' messages that we
could receive from the fingerprint service, as it may be configured to
handle more retries than us and they might arrive before we have
cancelled the verification session.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1652>
Decouple the verification failure count increase from
_verificationFailed as there are some cases in which we may want to
increase it without emitting a verification-failed signal.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1652>
When the login/lock screen is shown the error messages for background
services are always ignored.
However, in case the service is the fingerprint authentication method
we still want to be able to show error messages to inform the user
about what failed, and eventually that the max retries (that may be
different from the login screen configuration) has been reached.
This handles partially the design issue [1] related to the login/lock
screen fingerprint authentication.
Eventually we want to use pam extensions to use clearer and parse-able
messages, however in the case of the fingerprint service we can be sure
that the fprint PAM module will only send errors on auth failures.
[1] https://gitlab.gnome.org/Teams/Design/os-mockups/-/issues/56
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1652>
When verification failed using a specific authentication service we're
currently restarting the whole user authentication system, which leads
to lots of unneeded operations (reinitializing a new user verifier proxy,
restarting all the gdm workers with the relative PAM modules and so on).
And this makes also debugging of login problems more complicated, given
we're cluttering the journal with repeated data.
However, at reauthentication failure GDM has already set up for us an
user verifier that we can use reuse to start only the service that had a
failure. So when possible, just start a new service instead of rebooting
the whole authorization process.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1622>
When retrying the authentication we should make sure that all the
previously initiated services are stopped in order to begin a new
authentication session with all the configured services.
Unfortunately at the current state we only dispose the currently used
user verifier, but we don't make it to stop all the relative gdm workers
and then they'll stay around potentially blocking any further usage of
them (as it happens with the fingerprint one, that has unique access to
the device).
So, cancel the currently running authentication before starting a new
one if we're explicitly retrying.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1622>
In case a background service such as the fingerprint authentication
fails to start we'd just mark the whole authentication process as
failed.
Currently this may happen by just putting a wrong password when an user
has some fingerprints enrolled, the fingerprint gdm authentication
worker may take some time to restart leading to a failure and this is
currently also making the password authentication to fail:
JS ERROR: Failed to start gdm-fingerprint for u: Gio.DBusError:
GDBus.Error:org.freedesktop.DBus.Error.Spawn.Failed:
Could not create authentication helper process
_promisify/proto[asyncFunc]/</<@resource:///org/gnome/gjs/modules/core/overrides/Gio.js:435:45
### Promise created here: ###
_startService@resource:///org/gnome/shell/gdm/util.js:470:42
_beginVerification@resource:///org/gnome/shell/gdm/util.js:495:18
_getUserVerifier@resource:///org/gnome/shell/gdm/util.js:405:14
async*_openReauthenticationChannel@resource:///org/gnome/shell/gdm/util.js:378:22
async*begin@resource:///org/gnome/shell/gdm/util.js:194:18
_retry@resource:///org/gnome/shell/gdm/util.js:561:14
_verificationFailed/signalId<@resource:///org/gnome/shell/gdm/util.js:584:30
_emit@resource:///org/gnome/gjs/modules/core/_signals.js:133:47
finishMessageQueue@resource:///org/gnome/shell/gdm/util.js:268:14
_queueMessageTimeout@resource:///org/gnome/shell/gdm/util.js:273:18
_queueMessageTimeout/this._messageQueueTimeoutId<@resource:///org/gnome/shell/gdm/util.js:288:65
Given that background services are ignored even for queries or any kind
of message, we should not fail the authentication request unless the
default service fails.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1622>
When a verification session has failed we may want to wait for the user
to have completed all the waiting queries and to have read all the
incoming messages, however during such time an user verifier should
not be allowed to queue further messages to the UI, as we're about to
completely stop the identification or start a new one.
Unfortunately this is not true because we're still connected to the
identifier signals, and so we may still show messages.
This is particularly true when using the fingerprint PAM module as it
may restart the authentication while we're in the process of stopping
it.
So, keep track of all the signals we've connected to, and disconnect on
verification failed and during cancel/clear operations.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1622>
Answering a query may be delayed to the moment in which we've not any
more messages in the queue, however this case can also happen just after
we've cleared the UserVerifier and in such case we'd have nothing to
answer, but we currently throw an error:
JS ERROR: Exception in callback for signal: no-more-messages:
TypeError: this._userVerifier is null
answerQuery/signalId<@resource:///org/gnome/shell/gdm/util.js:249:17
_emit@resource:///org/gnome/gjs/modules/core/_signals.js:133:47
finishMessageQueue@resource:///org/gnome/shell/gdm/util.js:266:14
_clearMessageQueue@resource:///org/gnome/shell/gdm/util.js:301:14
clear@resource:///org/gnome/shell/gdm/util.js:223:14
cancel@resource:///org/gnome/shell/gdm/util.js:205:18
reset@resource:///org/gnome/shell/gdm/authPrompt.js:482:32
cancel@resource:///org/gnome/shell/gdm/authPrompt.js:569:14
vfunc_key_press_event@resource:///org/gnome/shell/gdm/authPrompt.js:128
So handle this case more gracefully keeping track of the current
cancellable and checking whether it is still valid before trying to answer
a query or do a delayed action.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1622>
As per previous commit the user can cancel an ongoing authentication via
Escape key and that will always send the user back to the clock view in
lockscreen or user-selection view in login prompt.
However, we can be a little more permissive and don't switch view to be
able to restart the authentication without further action.
To avoid this to be abused though, we consider the user verification
cancellation via escape key to be a "soft-failure", so once the
configured "allowed-failures" gsettings value has been reached, we'd
just act as before, ignoring any further request (until we don't get
back to the user auth view).
In this way we still make brute-force attacks harder to do, while still
giving the well-behaving user some ability to fix mistakes.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1622>
Escape key is supposed to cancel a verification, however if the user
already hit Enter to begin the authentication the Escape key won't work
until the verification completed.
This may be quite inconvenient when an user did a typo while writing and
wants to cancel the already started auth.
So, while authenticating (or in general while the entry is unsensitive)
give the key focus to the authpromt itself so that we can still get the
input events and cancel an user action.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1622>
When a cancel event in the user lockscreen happens we first emit a reset
signal and immediately a cancelled one.
This lead to start a new gdm worker for each enabled authentication
method and then immediately to stop it.
As per the previous commit, we don't have anymore dangling gdm workers
around, but still we should not even start a new one in such case.
So, when the user explicitly cancelled the authentication session, first
emit a cancelled event and only emit a reset event with a begin request
if we are outside the lockscreen.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1622>
When we cancel an user authentication via Escape key or cancel button on
AuthPrompt we reset the view and we emit a 'cancelled' signal that leads
to destroying the auth prompt and the user verifier.
However, the verifier may still have an operation in progress and its
completion may take some time (as in the case of gdm-fingerprint), but
we just leave the gdm worker running until its pam module completes
(potentially never) clearing and disposing its handle.
So, instead of just clearing the verify, actually cancel and clear it.
In case the user verifier is set, clearing the relevant data will happen
anyway as part of the cancel() call.
Ideally this would have been handled by gdm itself, but unfortunately we
can't fix it there because the verifier itself is a class generated by
gdbus-codegen, so we can't handle this automatically on disposal nor we
can automatically monitor when the caller proxy is stopped on our side.
Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3654
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1622>