Using pythons webbrowser.open in snaped applications

Hello everyone,

in my python application I’m using webbrowser.open from the python standard library to open website links from within my application. This does work fine outside of snaps as expected, but as soon as I try to open them from a snap application it fails with

Error org.freedesktop.DBus.Error.ServiceUnknown: The name io.snapcraft.Launcher was not provided by any .service files
Error org.freedesktop.DBus.Error.ServiceUnknown: The name com.canonial.SafeLauncher was not provided by any .service files

Is there a way to get this to work or do I need to change to xdg-open which I’ve seen should be able to be called from snap applications, even though it’s not as straight forward for end users as they have to install extra dependencies as far as I know.

Change to “core candidate” as a first try:
snap refresh --candidate

After that you might need to use:
sudo /usr/lib/snapd/snap-discard-ns SNAP_NAME

For details have a look at xdg-open-regression.

changing core snap to candidate and calling snap-discard-ns makes the errors disappear, but it doesn’t open the URL in a webbrowser.

Could it be a problem, that I close the application right after opening the URL?

Do you have the snapd-xdg-open deb installed? (That could be the next test step.) :wink:

yes, I do have snapd-xdg-open installed. I’m not sure though, if webbrowser.open even uses xdg-open.

Unfortunately SNAPPY is not always straightforward, so the next try could be a call of xdg-open instead.

I do not know anything about webbrowser.open, sorry.

Ok, will try with xdg-open for now then. Thanks!

Using xdg-open results in a permission denied error.

  File "main.py", line 337, in __quitApplication
  File "/usr/lib/python3.5/subprocess.py", line 947, in __init__
    restore_signals, start_new_session)
  File "/usr/lib/python3.5/subprocess.py", line 1551, in _execute_child
    raise child_exception_type(errno_num, err_msg)
PermissionError: [Errno 13] Permission denied

very important: make sure to not have xdg-open inside the snap (do not put it into stage-packages or build-packages)…

@sergiusens What do you think about blacklisting certain packages from stage-packages? Certainly xdg-open would be a candidate.

1 Like

We already do that per base, so if you build on 16.04 LTS there’s a list of dependencies we do not follow unless explicitly stated.

Per base? Can you elaborate please.

Sorry, I got it mixed up with another feature, this is the list https://github.com/snapcore/snapcraft/blob/master/snapcraft/internal/repo/manifest.txt

I just checked, xdg-open is not in the resulting snap. Also I have not put it in the yaml file anywhere explicitly. So that should be fine.
Anything else that I can check?

What is the permission denied about? What is it trying to run and being unable to?

It should definitely be able to execute xdg-open.

I’m not sure what the permission is about. All I do at that time is
subprocess.Popen(["xdg-open", self.website])
where website is a simple website URL either to my website or to an irc channel.

Just an idea:
“xdg-open”, self.website [as is]
“xdg-open_”, self.website [transform, do not use]
"xdg-open ", self.website [solution!?]


EDIT: Added the: [explanations]

1 Like

I’ve tried with the underscore and the space at the end, both end up in a file not found error e.g.

FileNotFoundError: [Errno 2] No such file or directory: 'xdg-open_'

not sure what’s the difference in your first version though.

Sorry, the underscore was only to “show” the gap.

I don’t know your surrounding, it was only an idea that you might call
xdg-openhttp://xyz.ab instead of xdg-open http://xyz.ab.


With Java you could make it in this way:
Runtime.getRuntime().exec("xdg-open " + infoUrlString);

Sorry, I forgot there were recent changes around this. Access to xdg-open was just recently opened up as you can see in this conversation.

As an easy workaround, you can try copying the trivial xdg-open script in your snap for the time being, until this change goes live in an upcoming core snap. The script is just a shell line sending a message over DBus.

Please let us know how it goes, and I’m sorry for the trouble there.

1 Like