-
-
Notifications
You must be signed in to change notification settings - Fork 207
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow host apps to register themselves #1521
Allow host apps to register themselves #1521
Conversation
6c33ebe
to
cf508ac
Compare
As much as I admire your optimism, I have a pretty hard time believing apps will "fix themselves" by calling a D-Bus API (or using libportal) for the unsandboxed case. You're still asking application developers to deal with this case. Might as well ask them to call: setenv ("XDP_PROP_application_id", "com.example.App"); in their |
One could equally argue that apps only have to call |
For apps that wants to support running non-sandboxed that uses libportal or ashpd could perhaps use API like For apps that interact directly with the portal using D-Bus it seems like a trivial thing to make just another method call before anything else.
Using |
One could check that and skip Anyway, I do agree that calling one more portal helper function or calling one more dbus method when one wants to interact with portals shouldn't be much of an issue. |
@Sodivad and I were musing on this a bit from the KDE side of things. It generally seems like a good idea, so +1 from us A getter might be handy for the unforeseen scenario where the app (e.g. inside a library) wants to know its own app id. It'd be good to document whether the registration is per-pid or per-connection (e.g. say I open multiple dbus connections in my app - do I want to make sure that all of them are registered with the portal or is one sufficient so the pid is associated?) Maybe also document what happens when Register is called more than once (possibly with conflicting information?). |
Seems like a harmless thing to add. Apps must know it's only a host-app thing though, since this API namespace won't be available in sandboxes.
That is a good question. Making it per pid makes sense unless apps expect to be able to have different hats from the same process. Seems unlikely, and simply impossible would they run in a sandbox. |
The famous one would be Libre Office where afaiu everything is a single process even windows can appear as differnt apps writer, calc, impress.. |
Then perhaps for consistency, it should still be per pid here still, so that it doesn't work all too differently running LibreOffice inside or outside of a sandbox, to avoid both developer and user confusion. |
Sounds reasonable 👍 |
This would solve the massive headache of launching apps from terminal windows giving incorrect app IDs and absolutely requiring either a wrapper to execute an app or launching the .desktop through a graphical interface When working on global shortcuts portal adoption, it's not been great running an app from a terminal window, or as a child process of something, and then it has a blank appid so the portal backend either doesn't register your shortcuts or it generates a random appid based on the session token. In KDE specifically, you will then have a random token as the app name in the system settings, which is pretty bad for UX. It turns out most apps don't run their children in spec conformant systemd units I have a feeling though that the automatic app id registration should be kept as a fallback in case an app doesn't register an app id. App ID being guaranteed to match a desktop entry by default, or being empty, (or flatpak/snap) is useful for fetching display names from the .desktop and other info automagically, which is now done in xdp-kde (see https://invent.kde.org/plasma/xdg-desktop-portal-kde/-/merge_requests/341). But an app not being able to register its own app id is a much bigger headache than not being able to fetch a display name. |
cf508ac
to
ed8ac44
Compare
Pushed an implementation, but now noticed we had discussed pid vs peer:
It's not yet doing that, and doing so will already address issues I ran into when updating libportal's qt examples, where the app ID for connections from Qt resolve differently to the libportal connection. |
|
||
if (!app_info) | ||
{ | ||
gboolean is_sandboxed = FALSE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe instead of having this duplication we could call xdp_connection_create_app_info_sync
and xdp_app_info_is_host
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did that in an earlier iteration, but changed to this approach to not have this code path go through potential creation of non-host apps. I think this ended up nicer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is that undesirable? Creating XdpAppInfo's is side-effect free.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my opinion, trying to fully fledged objects, when there were no intention to use them, since only the condition for them to be created was of interest, wasn't nice. The relevant condition also became somewhat hidden. Thus I ditched complicating create_app_info_sync()
and made the paths separate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -867,25 +866,19 @@ xdp_connection_create_host_app_info_sync (GDBusConnection *connection,
if (!app_info)
{
- gboolean is_sandboxed = FALSE;
-
- if (!xdp_is_flatpak (pid, &is_sandboxed, error))
- return NULL;
-
- if (is_sandboxed)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Can't manually register a flatpak application");
- return NULL;
- }
+ g_autoptr(XdpAppInfo) detected_app_info = NULL;
- if (!xdp_is_snap (pid, &is_sandboxed, error))
+ detected_app_info = xdp_connection_create_app_info_sync (connection,
+ sender,
+ cancellable,
+ error);
+ if (!detected_app_info)
return NULL;
- if (is_sandboxed)
+ if (!xdp_app_info_is_host (detected_app_info))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Can't manually register a snap application");
+ "Can't manually register non-host applications");
return NULL;
}
What's the problem with this? It exactly tells the reader the condition under which it is not allowed while also abstracting away any engine specifics.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO that is not better. It creates something based on some logic inside create_app_info_sync()
which needs to become a bit more complicated, then checks if it did the right thing, instead of checking the condition, then explicitly creating the right thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(applied the rest of the review changes https://github.com/swick/xdg-desktop-portal/tree/refs/heads/wip/host-portal-registry)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, but you're creating more code to make this piece here more error prone than it needs to be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a different opinions here I guess, you say "create dummy objects" which I found awkward because one use API in a way it isn't intended to, and I say "don't create dummy objects" which you find awkward because things become a bit more open coded.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not a dummy object, it's the XdpAppInfo that results from auto-detection and you ask it the question you actually want an answer to which is "is this connection from a host" instead of "is this connection a flatpak or snap".
@@ -187,6 +188,33 @@ export_portal_implementation (GDBusConnection *connection, | |||
g_debug ("providing portal %s", g_dbus_interface_skeleton_get_info (skeleton)->name); | |||
} | |||
|
|||
static void | |||
export_host_portal_implementation (GDBusConnection *connection, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit unfortunate that this function doesn't by itself make sure that only host apps can call interfaces exported by it. The burden is currently completely on the implementation.
if (app_info) | ||
app_info_kind = "flatpak"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (app_info) | |
app_info_kind = "flatpak"; | |
app_info_kind = "flatpak"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating app_info
might have failed, and don't want to set it if it did, even if it'd be overwritten eventually.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The other ones do exactly that though, so this isn't consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What other ones do you mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
app_info_kind = "snap";
and app_info_kind = "derived host";
below
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, indeed. The intention was to make those who conditionally work conditionally set it, but seems I did the wrong thing for the snap case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the point is that none of the ifs here do any work and are just noise
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the other hand, not conditioning them ends up with intermediate incorrect state, which I found misleading.
Would it make sense to do this in GApplication (in addition to libportal/ashpd) if the application-id property is set? |
77ab91f
to
bd47696
Compare
Perhaps, I wonder if it should be possible to calling Register() multiple times with the same application ID to make this easier, or whether apps should know whether Q/GApplication does it for them. Pushed a branch that allows that here: https://github.com/jadahl/xdg-desktop-portal/commits/wip/redundant-register |
bd47696
to
35da526
Compare
a4e68c4
to
291e77c
Compare
The second connection should inherit the app-id from the first.
This is currently not allowed.
5633f7f
to
5bb5595
Compare
I have no opinion on error vs success on registering with the same ID as well. |
GLib implementation: https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4465 |
Alright, let's go with the current implementation then. We could relax this later on. |
What happens if xdg-desktop-portal isn't running yet when the application attempts to register itself, or if xdg-desktop-portarl crashes, or if it gets manually restarted by running |
This looks a lot like it duplicates the session management protocol: It would be great if we could avoid another sync call in the startup path for every application, given that information (app ID, app’s D-Bus connection name) is already available to the session manager. Could the portal query this information from the session manager when it’s needed (potentially with a bulk query too, allowing for O(1) calls rather than O(N) in the number of apps)? Apologies if this has been covered already or is inapplicable for some reason, I only skim-read the many comments above. |
There is no session management shared interface: it's only available on GNOME and Xfce. We might end up with a Wayland protocol for session management, but right now it's still an open issue if the session object ought to be tied to an application id. Portals are supposed to work in multiple environments, and not all of them have a session manager. |
They indeed need to re-register, ideally by listening to the portal name coming back. Something libportal ideally should handle itself.
It doesn't need to be sync, does it? The app can continue the same no matter if the call succeeded or not. |
OK, that should work, but it should be documented more clearly. Plenty of applications talk to portals directly without using libportal, and developers won't know to implement this manually if we don't draw some attention to it. |
Synching up between session manager and portals about some newly appeared application sounds difficult at best |
Georges asked me to comment further on this, and I think I’ve settled my thoughts. So:
|
So we need this after all.
xdg-desktop-portal is desktop agnostic why should it explore an interface that only gnome implements.
This is not a session managment protocol. If you worry about sync dbus calls on startup, it doesn't need to by sync and can be async just fine (that's what my Qt impl does) You also fail to consider non-GLib apps running on Gnome, which do not use the gnome session managment. |
Yes, I said that.
aiui it’s about associating an app’s D-Bus session bus connection with the app ID and cgroup. That counts as session management, in my book, even if it doesn’t do all the same things as other session management protocols.
Perhaps I shouldn’t have emphasised sync. Sync calls on startup are terrible, but async calls still raise all the questions of what to do if they fail, time out, etc. IPC is not simple, doing less of it is always better. |
I don't see what the session is here? The dbus connection?
Nothing. This whole registry is band aid.
This is not a portal though, and the flow is backwards: the client, not some backend, provides this information and that's the entire point of it. |
I think the bigger issue would be potential races. In snapshots we call the camera portal asap and this is yet another thing that might be not be done before we need the app id. |
Then you can call it yourself and let the gtk/glib one potentially fail. |
I already have MRs for Firefox and Chromium, both also call the settings portal to get color scheme right early in the initialization and I was still able to make it work. I believe every app should be able to find a way to make a proper use of this API. |
It bears repeating: this is band-aid. It's a tool for apps to work around the system not putting them into an appropriate cgroup. I honestly don't care if we put the band-aid into gtk/glib or not. What we really should put there is some code that makes sure we spawn apps into the right cgroup. |
When not under a sandbox, register the app with the new host app registry in XDG Desktop Portal. This allows host system apps be better recognized, and behave a little better, when interacting with portals. This has to happen very early during initalization, before even the gtk_init() call, because e.g. on Wayland the Settings portal is used when opening the display. See flatpak/xdg-desktop-portal#1521
My concern with the registry is it's being presented as a temporary band-aid solution, which doesn't make sense to me at all since creating a new D-Bus API seems like a very permanent solution. But I have no objection to just keeping this registry API around forever. It works and it solves the problem, right? Why not? |
For host apps, we currently require applications to run inside a cgroup with a name that allows xdg-desktop-portal to derive an application ID from it. This does not work reliably, and while the situation can improve, it's unlikely to ever be fool proof, as it in theory requires every potential piece of software that launches other applications to know how to launch it in a compatible way.
Cgroups is also a Linux specific API, which is problematic from a *nix wide portability perspective.
To address this, introduce a host-only portal API that allows applications to register their D-Bus connections, associating them with an application ID. This moves back the burden of associating an application with an application ID back to the application itself, instead of the application launcher.
Applications calling this overrides any applicion ID derived from the name fo the cgroup the application runs inside.
I'm not saying we should do this, but perhaps it is something we should consider doing. Relying only on cgroups is a noble idea, but it hasn't worked well so far, and while it's possible that at least a majority of cases can be handled by peeking at it and deriving the application ID, it's also likely that there will always be cases where it won't work, without any way for applications to get themselves to work.
Some downsides include:
Some upsides: