Integrate snapd-xdg-open into snapd repository

After being back from holiday I started this morning to polish the PR.

2 Likes

I did a first update of the PR but now need to fix the spread test case for Ubuntu 14.04 and then we should be ready to go.

2 Likes

Hi,

is there any known problem about xdg-open not being executable by the snap?

In my snaps I don’t see it (I just do mount | grep snap and then inspect the contents), although I can see in /snap/core/current/user/bin

Also, I get this error when I call it via child_process:

/bin/sh xdg-open object not found (is like the binary or script is not there)

To test that is not my code, I also tried with the snapcraft-forum app and I got the same error when I try to open an external link.

I’m using the latest version of snap and I’m including the unity7 interface (I use electron builder for that) and everything seems to be correct.
I also tried to forcing the path to /usr/local/bin as some one suggested but since there is no binary or script there I got a similar error.

Any ideas?

Update, here is the complete javascript error:

Uncaught Exception:
Error: Command failed: xdg-open file:///home/moodle/snap/moodlemobile/x1/com.moodle.moodlemobile/sites/81f05127ddc52d78f935288c2c670dd8/filepool/DigitalLiteraciesTranscript_8ccfd589eb4bd1375c7a63c7085de0d2.pdf
/bin/sh: 1: xdg-open: Permission denied

at checkExecSyncError (child_process.js:502:13)
at Object.execSync (child_process.js:542:13)
at Object.childProcess.(anonymous function) [as execSync] (ELECTRON_ASAR.js:685:22)
at EventEmitter.ipcMain.on (/snap/moodlemobile/x1/resources/app.asar/www/electron.js:131:19)
at emitTwo (events.js:106:13)
at EventEmitter.emit (events.js:191:7)
at WebContents.<anonymous> (/snap/moodlemobile/x1/resources/electron.asar/browser/api/web-contents.js:256:37)
at emitTwo (events.js:106:13)
at WebContents.emit (events.js:191:7)

So I eventually made xdg-open work but the problem is that it seems that snapd-xdg-open only accepts URLs (so if I try to open another file it will return an error “Protocol not supported”)

So my question is: is there any way to open files (with the default app for the file type) downloaded via a snap app?
Our app is a desktop version of Moodle Mobile. Moodle is an LMS (tool for delivering online courses) so most of the courses include pdf files. Right now, with snap, we can’t launch the pdfs (or any file) downloaded by the user (I tried things like embedding file browsers like xfe or trying to launch nautilus etc…) but it seems that it is not possible unless using an interface and I don’t see any interface suitable for launching files.

xdg-open is currently filtering the protocols on both sides, in the helper we ship in the core snap and the dbus service that snapd-xdg-open ships.

There is a re-write in the works that is discuseed in the thread below:

I know that @niemeyer has some opinions about the filtering, so I’m not sure what the limits are in which we want to extend the filters with new protocols.

Thanks for your reply, so it seems that for the time being there is no a simple way for launching files in other system applications via snap.

I did additional research to see how this is achieved by Ubuntu touch apps (to see if they implement a system like Android intents) but I found nothing so I assume that, for now, the only solution would be to integrate a preview app inside our snap so we can launch it to display a preview of the files downloaded (with some limitations like there won’t be a way to launch the original file).

In any case, I’ll check a few months again

Well, adding pdf to the allowed mime types is pretty trivial, the question is if this is wanted by the architects (which is why i summoned @niemeyer above)) in this form.

Just adding the change is a few minutes work and would be possible to land with the next stable core release (and snapd-xdg-open package).

@jleyva It’s generally not a job for snapd itself to support opening all kinds of URLs. Instead, it mediates into whatever the platform of your choice is. The xdg-open trick is a good one, and we’re improving it further, but it’s not the only way you can open other applications.

If you provide further details about what you’re trying to do, we’d be happy to assist you in having the proper API in place, and we even if there’s no convenient mechanism to support it exactly what you want right now, you might try to get a classicly confined snap in place which would allow traditional access into the underlying system, while we nail down the details of strict confinement.

@niemeyer thanks for your reply.

I will try to explain clearly what are we trying to achieve. Our app is a Desktop client for Moodle. Moodle is an LMS (a tool for providing online courses), in some aspects is similar to a CMS because you can create contents that will be delivered to students.

When a teacher creates a course, he can add activities like forums, quizzes or he can upload files for the students to download (like a pdf, a presentation, a mp4 video or an audio).

The student should be able to use our desktop app to download the course contents and open them when he is not connected to the Internet. For example, he should be able to download the pdf, presentation and videos. Once the contents are downloaded to the user home he should be able to open them via the same interface in the app he used to download them.
Basically, he see in the app a list of contents with an icon that indicates that it has been already downloaded. If he clicks on the icon, the app should open the local document using the default application in the OS.
We have everything working right now in Linux. The problem is that when we create the strict snap everything works fine except launching the downloaded files using the OS default application for the extension/mime type. We made snapd-xdg-open work but we noticed that only supports URLS (not files).
So, right now, we can’t use snap (we could use the classic confinement but it seems that is not supported by most of Linux distributions and part of the Moodle open philosophy is to be available in any type of device).
In brief: we need a way to allow strictly confined snaps to open files using the OS default app for the extension.

I see, thanks for the details.

What extension/mime type do you need to be handled by your application? Is there a standard mime type (say, for a PDF) or is it custom to your application? Perhaps can you point me to the diff of the change you produced for snapd-xdg-open, so I can have a more clear idea of what you need?

We have some changes in progress right now for snapd-xdg-open, so I’m keen on making sure your use case is either already handled or at least that it will be in the near future.

Hi,

our app should be able to open any type of file.

Basically, it does the following:
When the user click on the name of one content downloaded the following code is executed in a child process:
xdg-open path_to_file

See the following screenshot, in this case the user clicked in the “Download the video script” link that it is a pdf file that was downloaded a few days ago. The app will execute xdg-open and the OS will open the PDF viewer (in this case the Ubuntu one):

Thanks for the example. Yes, this is the sort of thing that the on going work on the internal xdg-open will improve significantly.

The easiest way to get started would be to produce a classic snap indeed. Then you can easily migrate over to the new xdg-open support once it lands.

Thanks for your continuous support. I already created the classic snap and it is working as expected now (it opens any file via xdg-open). There are some app functionalities not working yet (like audio or video recording using web apis (our app is built on top of electron) but I’ll open a separate topic if we are not able to fix them.

For future reference if anyone else experiences the issue: If you are using electron-builder for creating a classic snap, once is created you need to edit the .yaml file and remove the desktop-launch from the command: line (and do a manual build via snapcraft snap). The reason is that classic snaps don’t support desktop-launch since it is not necessary.

This should probably be modified to “any type of file, provided the app has read access to it”.

Interestingly, xdg-desktop-portal splits this into two methods:

  1. OpenURI, which takes a string URI and specifically rejects file:/// URIs.
  2. OpenFile, which takes a file descriptor and determines the file name by reading the /proc/self/fd/$fd symlink. This ensures that the app can actually open the file in question.

Hi,

yes, exactly, if the app has access to the file it should be able to open
it. In our case, all the files are downloaded to the user home that is
already accessible by snap so it should be fine.

Is there a PR or 2 I can follow for progress on this?

Recently did an install of Fedora 26 and eagerly installed all of my snaps because I knew snaps are cross platform. But can’t open links from any of them. Then I remembered this discussion. It appears that snap-xdg-open isn’t available on fedora so that shim isn’t available in the stop gap like on Ubuntu.

1 Like

@morphis is on this, and I need to catch up with the latest developments in the PR:

https://github.com/snapcore/snapd/pull/3260

We need to think through the safety implications of that a bit more. In particular, the application can of course read any of its content, but are we sure that it’s okay for any of the registered handlers to open the given file as well? Probably not.

That’s definitely something worth considering.

For what it is worth, xdg-desktop-portal's URL/file opener service pops up a confirmation dialog when used (along with an option to always allow the given application to open URLs/files). This also has the benefit of letting the user know which application caused the web browser to open / gain focus.

Given that we (the desktop team) want to make xdg-desktop-portal available to snaps, I do wonder whether we should consider migrating to it as the default solution. It is not at all clear that there is a need for something that will work outside of a desktop session, or what kind of semantics would make sense there. It certainly isn’t a use case that apps would expect to work outside of the sandbox.

That’s a great idea. We have the snap userd daemon work coming for a while, by @morphis, so I’d suggest not mixing that in until we get that PR landed, but would be happy to work with you to support that as the default approach next.