Skip to content
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 a flatpak to discover/call another flatpak #283

Open
Jehan opened this issue Dec 7, 2017 · 34 comments
Open

Allow a flatpak to discover/call another flatpak #283

Jehan opened this issue Dec 7, 2017 · 34 comments

Comments

@Jehan
Copy link

@Jehan Jehan commented Dec 7, 2017

Hi!

GIMP has this nifty new feature for opening RAW images, which is we use third-party advanced RAW software for the job. The idea is: why bother reimplementing a shitty 3-slider RAW developer as a plugin which will mostly be a toy when there are really good complete ones, and several being Free Software, like darktable or rawtherapee.
So now when someone tries to open a RAW in GIMP, we detect installed darktable and rawtherapee and redirect the call to the user's favorite RAW software (if both are installed, one can choose one's favorite in GIMP's preferences). When the editing stops on this third-party software, it automatically sends back the result to GIMP for further editing.

Unfortunately this feature stopped working with flatpak. Flatpaked GIMP don't see DT/RT installed by the system packaging, nor installed as flatpak.

Let's say we don't mind not detecting non-flatpak DT/RT. After all, flatpak is a sandbox and one of the goal is to shield the system. But couldn't there be an API to detect other flatpaks and being able to run them? I see there is a darktable flatpak for instance. It would be awesome if we could detect it within GIMP flatpak and run org.darktable.Darktable.

@TingPing
Copy link
Member

@TingPing TingPing commented Dec 7, 2017

You can open URIs but it doesn't work for local file://'s so that is probably the best way to expose that. It does create an easy sandbox escape but the user will have to explicitly allow it.. don't know if that makes it ok.

Loading

@Jehan
Copy link
Author

@Jehan Jehan commented Dec 7, 2017

How would it work exactly? I'm not sure I understand your workaround.

For info, right now (out of flatpak), we discover the third-party app in a Linux OS by simply checking its availability in the path.

Loading

@TingPing
Copy link
Member

@TingPing TingPing commented Dec 7, 2017

You let the host handle file associations and you would just pass it the raw file.

Loading

@Jehan
Copy link
Author

@Jehan Jehan commented Dec 7, 2017

Not all RAW software will work well with GIMP (currently only darktable and rawtherapee). There is a coded layer between GIMP and the RAW software. This specific feature has been closely created together by developers of all 3 projects (GIMP, darktable and RawTherapee) so that there is a back-and-forth interaction/connection.

In particular if we just let file association handle the file, once the user is done developing the RAW, the third party software would not give back the result to GIMP. And that also means we can't just give the file to the RAW software in a common way. GIMP actually runs a command with specific options.
Here is the workflow currently:

  • the photographer opens a RAW file in GIMP;
  • GIMP automatically opens the RAW file in DT/RT;
  • the photographer tweaks/develops the image in DT/RT;
  • when finished, the photographer closes DT/RT (no need to save/export anything);
  • GIMP automatically loads the result of the developed RAW;
  • the photographer can continue working on the image in GIMP.

So no, we can't just let the host handle file association. The point is not to redirect the file towards some other software and not hear about it anymore. That feature would make no sense at all (if that's what we want to do, we'd just say we don't support RAW images). The point is acknowledging that the RAW development is better done in a specialized software, but further image editing are better done in GIMP. This is basically a workflow where various more specialized software work together seamlessly and are connected, sharing images and work-in-progress at different steps, like a "Free Software graphics suite" or something.

Loading

@matthiasclasen
Copy link
Contributor

@matthiasclasen matthiasclasen commented Dec 7, 2017

Well, thats just not how sandboxes work: they isolate applications from each other and from the host system. If you want deep integration, you can ship the auxiliary software as part of your flatpak, and have it run in the same sandbox. Otherwise, you may need an api between the two apps to facilitate this sort of interaction. A d-bus api would be much easier to integrate in the existing tooling than launching the app with special options.

Loading

@Jehan
Copy link
Author

@Jehan Jehan commented Dec 7, 2017

Ok we'll discuss this.
It may indeed be better than a flatpak-specific communication protocol.
I opened this on our side: https://bugzilla.gnome.org/show_bug.cgi?id=791362

Loading

@matthiasclasen
Copy link
Contributor

@matthiasclasen matthiasclasen commented Dec 31, 2018

This is basically a portal question, so moving it over to xdg-desktop-portal

Loading

@matthiasclasen matthiasclasen transferred this issue from flatpak/flatpak Dec 31, 2018
@wjt
Copy link
Contributor

@wjt wjt commented Sep 3, 2019

Given an application-specific D-Bus API, and --talk-name=com.example.Foo in the app which needs to be able to tell Foo to do things, that app can tell whether Foo is installed by either trying to call a method on it (which would fail if it's not installed) or calling ListActivatableNames on org.freedesktop.DBus (the bus daemon itself, not the portal) to see whether it's present. The other half of this would be a “please install this app” portal.


The status quo is that, if you don't mind being GNOME specific and your app can talk to org.gnome.Software, you can tell it to show the details page for an app:

org.gtk.Actions.Activate("details", [GLib.Variant("(ss)", ("system/flatpak/flathub/desktop/org.gnome.dfeet/stable", ""))], {})

Or to install it (without user confirmation):

Activate("install", [GLib.Variant("(su)", ("system/flatpak/flathub/desktop/org.wesnoth.Wesnoth/stable", 1))], {})

Aside from the GNOME-specificity, there are some big caveats:

  • You have to know the remote name and branch name for the app
  • You can't tell when the app has been installed (or cancelled) without polling

I imagine that a better interaction would be (on GNOME):

  • App calls InstallApp(window_id, "com.example.Foo", {"preferred-remote": "org.flathub.Stable"})
  • If Foo is not installed:
    • User gets a cut-down version of the GNOME Software details page as a dialog, where they can choose to install Foo or cancel
    • Once they do one or the other, Response fires
  • If Foo is already installed:
    • Response fires at once? Unfortunately, this would allow any application to test for what other applications are installed, which has been deemed undesirable in the past, though at least the user would be spammed with dialogs for each app that's not installed so it would be visible…
  • Assuming success, App can now activate and talk to Foo over D-Bus

Seem plausible? @manuq can you comment from the point of view of wanting an API like this?

One thought was whether we could instead add a hint to OpenURI / OpenFile of the preferred application to use to open something, and in the case where that app is not installed, the portal could offer to install it.

Loading

@manuq
Copy link

@manuq manuq commented Sep 3, 2019

@wjt yes, your description matches exactly what an ideal portal API would look like.

  • Ability to check if another app is installed from a flatpaked app.
  • Ability to offer the user to install the app if not installed (through gnome-software in GNOME).
  • Continue the original app flow once the other app is installed.

And I agree, making this a user-facing portal mitigates the sandbox flaw of discovering other apps.

Regarding app A start talking to app B, our use-case only needs app B installed. We talk to gnome-shell to launch the other app with the org.gnome.Shell.AppLauncher.Launch() DBus method, and if that doesn't work we try org.gtk.Application.Activate().

Loading

@matthiasclasen
Copy link
Contributor

@matthiasclasen matthiasclasen commented Sep 3, 2019

I think sneaking this into OpenURI might not work for all cases - you might not have a uri / file to open with the app, but instead a D-Bus request to make, or sth.

The overall plan sounds good to me.

If we are concerned about discovering installed apps, we could add a separate permission for that.

Loading

@hadess
Copy link
Contributor

@hadess hadess commented Sep 3, 2019

One thing that I'm really not sure about is how you'd solve that original workflow without either questions that the user can't answer naturally, or a lack of question that would mean that too much is opened.

What would the UI look like for those apps? How do you trigger those links/API calls between applications?

From afar, it looks like a souped-up "OpenURI" with a signal back when editing is done, an "Edit In..." call, something which Android's Intent can already do.

Should this be part of a wider "Sharing" mechanism between apps instead? Or do we really want to poke holes just between those applications and no others?

Loading

@hadess
Copy link
Contributor

@hadess hadess commented Sep 3, 2019

Or do we really want to poke holes just between those applications and no others?

On that, applications from the same domain on iOS have more open permissions between themselves, so that Google's YouTube application can offer to open a location in Google's Maps application rather than in the native/default maps application. I don't know if there's a mechanism to do that for arbitrary applications though.

Loading

manuq added a commit to endlessm/clubhouse that referenced this issue Sep 6, 2019
This is implemented as a workaround for now, checking the output of
the flatpak command.

flatpak/xdg-desktop-portal#283
@treitter
Copy link

@treitter treitter commented Nov 5, 2019

Or do we really want to poke holes just between those applications and no others?

On that, applications from the same domain on iOS have more open permissions between themselves, so that Google's YouTube application can offer to open a location in Google's Maps application rather than in the native/default maps application. I don't know if there's a mechanism to do that for arbitrary applications though.

It looks like Universal Links allows one iOS app to open another by attempting to opening a URL. A special file on the web server is checked at the time the target app is installed to determine whether it allows other apps to make it open a given URL.

Notably, if the app is not installed, attempting to open a supported URL will open the URL in Safari; it won't take the user to the app's detail page in the App Store. The rationale is the user always gets an immediate, meaningful view of the resource without being prompted to install the app. But the website can have a clear "install the companion app for a better experience" link.

The Android approach is more flexible and respectful of the user's wishes though, so it seems like a better model for us. Eg, if there's an OpenStreetMap-based app that claims to support URLs like "https://maps.google.com/*", the user can set the default handler. My understanding is, on iOS, only the controller of maps.google.com is allowed to determine which (at most one) app is allowed to handle each URL regex starting with its domain.

Loading

@treitter
Copy link

@treitter treitter commented Nov 5, 2019

Though I guess the original topic is best supported by a custom URI. The specific apps that support it could register as supporting that scheme and the calling app won't have to hard-code their names or URL structures. Opening a generic URI is a bit different than a service-specific URL though and only the former is appropriate for passing arbitrary local data.

Sorry if the last comment was a bit of a divergence :)

Loading

@mrmcq2u
Copy link

@mrmcq2u mrmcq2u commented Nov 15, 2019

https://lists.freedesktop.org/archives/xdg/2014-January/013068.html - Problem 3 here is somewhat relevant.

Loading

@marcthe12
Copy link

@marcthe12 marcthe12 commented May 7, 2020

I see 3 use cases:

  1. Actually communication between apps via dbus or some other ipc.
  2. Basically a safer version of flatpak-spawn flatpak run
  3. Share a file/socket between 2 app (The orginal question).

Number 2 is needed for browser native messaging host system like firefox's. It could also allow run extensions that just provide binary run with another set of permissions. Inkscape has a cli and sandboxed latex will help alot.

Loading

@bnordgren
Copy link

@bnordgren bnordgren commented Nov 28, 2020

Just piling onto the discussion here. Other cross-flatpak dependencies (already packaged) are that the OpenShot app leverages both Blender and Inkscape.

One of the nice things about Flatpak is that the packaged apps don't need to be flatpak aware. Seems like many of the suggestions fundamentally want to change how programs are executed under linux. If an app has a preferences dialog to specify the path to another executable, why shouldn't I be allowed to type "flatpak run my.app.Here app " from within a sandbox? Or make a script in $HOME/bin that does the same? Seems like the choices are: flatpak adapts to apps as they are written, or it forces all app writers to add "flatpak support".

The simple solution, of course, is to build flatpaks with combinations of apps. Need access to another app? Bundle it. This also gives the package maintainer control over the version bundled.

Loading

@rugk
Copy link

@rugk rugk commented Nov 28, 2020

I think no adaption is required, you just need some patches to have – as you said – some script in a bin dir that then executes the flatpak run command. Patches, to make applications work better in flatpaks, are already used in many apps today on Flathub e.g., so this is not a problem IMHO.

Loading

@bnordgren
Copy link

@bnordgren bnordgren commented Nov 28, 2020

I don't believe you can currently call flatpak from within flatpak. Check out the following and tell me what I'm missing:

[bnordgren@mine Title]$ flatpak ps
Instance   PID    Application           Runtime
2257365655 327395 org.openshot.OpenShot org.kde.Platform
[bnordgren@mine Title]$ flatpak enter 2257365655 bash
[📦 org.openshot.OpenShot ~]$ flatpak ps
bash: flatpak: command not found

Need to have a command that runs before you can point an app to the command you want to run.

Loading

@rugk
Copy link

@rugk rugk commented Nov 28, 2020

No you cannot, but if this was implemented, the application inside the flatpak would not need to be adjusted, you would likely only need to put in some wrapper scripts for the used binaries.

Loading

@marcthe12
Copy link

@marcthe12 marcthe12 commented Nov 29, 2020

Lets raise this to flatpak to handle fine grained permission to flatpak(for all flapak commands, usefull fo flatseal software centre and this case) and also permission to expose ipc stored in $XDG_RUNTIME/app.

Loading

@bnordgren
Copy link

@bnordgren bnordgren commented Dec 28, 2020

Randomly casting about the internet, I learned about flatpak-spawn, which in line with my example up above should work like:

[bnordgren@mine]$ flatpak run --command=bash org.openshot.OpenShot
[📦 org.openshot.OpenShot]$ flatpak-spawn --host flatpak run org.blender.Blender
Read prefs: /home/bnordgren/.var/app/org.blender.Blender/config/blender/2.91/config/userpref.blend
/run/user/1000/gvfs/ non-existent directory
found bundled python: /app/blender/2.91/python
DEBUG:BlenderGIS-master.core.checkdeps:GDAL Python binding unavailable
DEBUG:BlenderGIS-master.core.checkdeps:PyProj unavailable
DEBUG:BlenderGIS-master.core.checkdeps:Pillow unavailable
DEBUG:BlenderGIS-master.core.checkdeps:ImageIO Freeimage plugin available

That opened the standard blender gui. Tweak the command line to put in the required command line arguments, and viola. From the man page (guess it still pays to RTFM):

       Unlike other flatpak commands, flatpak-spawn is available to applications inside the sandbox. It runs COMMAND outside the sandbox, either in another sandbox, or
       on the host.

       flatpak-spawn uses the Flatpak portal to create a copy the sandbox it was called from, optionally using tighter permissions and the latest version of the app and
       runtime.

Loading

@Taiko2k
Copy link

@Taiko2k Taiko2k commented Dec 29, 2020

@bnordgren That looks interesting, though I can't seem to get it to work myself. With --host I get the error Portal call failed: org.freedesktop.DBus.Error.ServiceUnknown. I also tried with --sandbox but with that I get bwrap: execvp flatpak: No such file or directory. Does using this require a special permission?

Loading

@bnordgren
Copy link

@bnordgren bnordgren commented Dec 29, 2020

Not that I know of. I just did that as a regular user on fedora 33 silverblue. My user account is in sudo/wheel, as it's the only non-root account on the system, but I didn't actually use any elevated privileges as far as I know. I'm what you might call a remedial flatpak user, not an expert. Others may have more insight.

Loading

@kon14
Copy link

@kon14 kon14 commented Dec 29, 2020

@Taiko2k flatpak-spawn's man page literally mentions you need to provide D-Bus access to org.freedesktop.Flatpak, granted this unto itself probably barely makes any sense to anyone unfamiliar with D-Bus and talk permissions in Flatpak.

Depending on the Flatpak you're trying to flatpak-spawn from you may already have talk access to that interface.
That's probably why yours and @bnordgren's results differed.

Try testing flatpak-spawn from any sandbox using the following:
flatpak run --talk-name=org.freedesktop.Flatpak --command=sh com.flatpak.Choice.

You may then make the changes permanent by registering the permission with flatpak-override.
Hope this helps.

Loading

@bnordgren
Copy link

@bnordgren bnordgren commented Dec 31, 2020

@kon14 Just out of curiosity, it looks to me that once these talk permissions are established, flatpak-spawn essentially acts like a get out of jail free card for any process in the sandbox. While useful in this case, it sure seems that this defeats at least the process-containment aspect of a sandbox. Is this accurate, or are there other controls which would prevent me from running arbitrary commands on the host (like sudo rm -rf /*) from within the sandbox?

Loading

@marcthe12
Copy link

@marcthe12 marcthe12 commented Jan 1, 2021

We definitely need fine grain permissions on flatpak-spawn. maybe we should have a sandbox flatpak command in a flatpak. flatpak-spawn flatpak override is a security time bomb. most people just need flatpak run or a few host commands. May be take queques from polkit

Loading

@kasperk81
Copy link

@kasperk81 kasperk81 commented Jun 10, 2021

Just wanted to bring up my browser integration use-case and the associated pain-points..


I have installed org.mozilla.firefox (for DRM stuff) and com.microsoft.Teams on Alpine Linux desktop (as google's DRM plugin windivine and msteams are proprietary software with no musl binaries .. obviously).

I received an email with invitation link to a Teams meeting.

If I click on the link in sandboxed friefox, the page it redirects to has an iframe with src value that looks like msteams:/l/meetup-join/19.... (long string). The page itself prompts to open msteam but naturally it is not discoverable in firefox sandbox.

Insult to the injury, there is currently no way to sign in using an invitation link in their desktop app..

So my workaround is to HTML decode that src value with quotes "msteams:/l/meetup...." and launch teams from suckless terminal:

$ flatpak run \
    --env=DBUS_SESSION_BUS_ADDRESS='unix:abstract=/tmp/dbusLcsUc61GBB,guid=c1005d826f37b49af839644f60bc4df0' \
    -vvv com.microsoft.Teams "msteams:/l/meetup-join....."
    
# that --env thingy is yet another workaround for https://github.com/flathub/com.microsoft.Teams/issues/61

Loading

@jokeyrhyme
Copy link

@jokeyrhyme jokeyrhyme commented Jun 10, 2021

what an ideal portal API would look like.

  • Ability to check if another app is installed from a flatpaked app.

There may be a fingerprinting risk here if flatpak apps can identify what other applications are installed on your system

It may be slightly better if they can only tell which protocols / message-types are handled and not exactly which apps are handling them?

An alternative with a worse UX could be to completely disallow any introspection of other protocols/apps, with the suggestion that every app that needs to call out to another one should blindly attempt it and also display instructions on-screen for users to install a recommended app if nothing happens (or, instead of instructions, a flatpak-managed button that streamlines the installation)?

Behavioural advertising has really ruined things for everyone here, and now we need to consider ways to block cross-app tracking :S

Loading

@jokeyrhyme
Copy link

@jokeyrhyme jokeyrhyme commented Jun 10, 2021

@kasperk81

I have installed org.mozilla.firefox (for DRM stuff) and com.microsoft.Teams on Alpine Linux desktop (as google's DRM plugin windivine and msteams are proprietary software with no musl binaries .. obviously).

I have a similar setup with Firefox, Discord, Slack, Zoom, and a whole bunch of similar apps all installed via flatpak, and I am able to click links in Firefox that result in being handled over in the Slack and other flatpak apps just fine

So, I believe the issue you've encountered is specific to Microsoft Teams and should be reported to them?

The issue, however, is still a good example of how easy it is for app developers to improperly register protocol handlers, etc, so maybe there's a documentation or other outreach fix that can be done here?

Loading

@gasinvein
Copy link

@gasinvein gasinvein commented Jun 10, 2021

There may be a fingerprinting risk

A flatpak app has numerous ways to identify the system it runs on, bind-mounted /etc/machine-id being the most obvious.

Loading

@jokeyrhyme
Copy link

@jokeyrhyme jokeyrhyme commented Jun 10, 2021

There may be a fingerprinting risk

A flatpak app has numerous ways to identify the system it runs on, bind-mounted /etc/machine-id being the most obvious.

TIL, I raised: flatpak/flatpak#4311

Loading

@kasperk81
Copy link

@kasperk81 kasperk81 commented Jun 11, 2021

being handled over in the Slack and other flatpak apps just fine

so if flatpaks can discover eachother already as you claimed, it means this issue (Allow a flatpak to discover/call another flatpak #283) is resolved from your point of view?

the issue you've encountered is specific to Microsoft Teams

No. My Firefox -> {any} integration just doesn't work. Nothing to do with any particular app. I have only shared a use-case.

The issue, however, is still a good example of how easy it is for app developers to improperly register protocol handlers,

not sure what is improper about it, but if you want any browser to prompt some application, URN is the standardized approach.

Loading

@jokeyrhyme
Copy link

@jokeyrhyme jokeyrhyme commented Jun 11, 2021

I've potentially misread or misunderstood, apologies

so if flatpaks can discover eachother already as you claimed, it means this issue (Allow a flatpak to discover/call another flatpak #283) is resolved from your point of view?

I did not mean to suggest that there was no more work to do here

My Firefox -> {any} integration just doesn't work. Nothing to do with any particular app. I have only shared a use-case.

Great, thanks for sharing this information

I think we might be discussing different things here

My understanding was that this issue was specifically for the use case that app A needs to communicate either specifically with app B, and for UX purposes needs to be able to know in advance if app B is even installed

The specific use case you've shared seems to be (correct me if I'm wrong) a hyperlink in a browser A, that is handled by app B

At the moment, the browser hyperlink case does work (except in your case, which seems very much like a bug, maybe it's worthy of a separate issue), but I agree that there's an opportunity there perhaps to improve the UX around it, because at the moment Firefox-in-flatpak defers to a non-specific "system handler" instead of knowing that e.g. a Teams links is supposed to be handled by Teams-in-flatpak

Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet