Open (pdf) file with Java8 app in external viewer

Hi,
I almost there with my snapification, looks like last problem to solve:

Snapified java 8 application doesn’t open requested file
minimal java to reproduce problem:

import java.awt.*;import java.io.*;
public class Main { 
public static void main(String[] args) throws IOException { 
  Desktop.getDesktop().open(new File("existing filet")); } 
}

internally java calls java sun.awt.X11.XDesktopPeer#gnome_url_show()

file that should be opened by Document Viewer (Evince in my case) ~/snap/e-mikrofirma/common/AKMF/emikrofirma/temp_15_132099972430572.pdf (or any other in user home dir)

snapcraft used to build app https://github.com/bademux/emikrofirma-snap/blob/master/snap/snapcraft.yaml

1 Like

gnome_url_show() can be found in the GVFS package so you’d want to edit your snapcraft.yaml with something like this
https://github.com/runelite/launcher/pull/92/files

I know it works to get web links to open but I’m unsure if it has the same effect on files, my temptation is to say you might need to use a system call to xdg-open with the file location which should work fine but might require you to do a conditional to check if you’re in a snap environment in the Java itself.

Incidentally, xdg-open would work on web links too, so depending on where you’re deploying the app, you might just want to prefer it on Linux over Java’s own function anyway, since Java’s own function wouldn’t work reliably on say Arch Linux where GVFS isn’t a preinstalled package if they weren’t using the Snap.

Edit:

I’ve been looking further into this today. Adding GVFS adding it to the LD_LIBRARY_PATH has some influence if you’re using the GTK2 Snapcraft Desktop Helpers, but doesn’t seem to work with the GTK3 Snapcraft Extensions. This seems to be because Java checks for some GTK2 and I’m not exactly sure the interplay between the various Gnome components.

I would still overall recommend considering using xdg-open directly, in Snap, it’s wrapped around desktop portals and should be far more reliable in general for confined applications.

Unfortunatly the recipe doesn’t help and app modification isn’t an option
After adding GVFS I got an exception:

java.io.IOException: Failed to show URI:file:/home/myuser/snap/emikrofirma/common/AKMF/emikrofirma/temp_12_158094824738822.pdf
	at sun.awt.X11.XDesktopPeer.launch(XDesktopPeer.java:123) ~[?:1.8.0_265]
	at sun.awt.X11.XDesktopPeer.open(XDesktopPeer.java:86) ~[?:1.8.0_265]
	at java.awt.Desktop.open(Desktop.java:269) ~[?:1.8.0_265]
	at a.a.a.c.c.d.h.EPF$1.HZI(Unknown Source) [?:1.3.0.10]
	at a.a.a.c.e.a.a.EVN.run(Unknown Source) [MicroLauncher.lib:1.3.0.10]

and I got this on start:

Gtk-Message: 23:20:43.953: Failed to load module "gail"
Gtk-Message: 23:20:43.953: Failed to load module "atk-bridge"
Gtk-Message: 23:20:43.983: Failed to load module "canberra-gtk-module"

If app modification isn’t an option, I think the options essentially become recompiling Java itself so you can patch the need for gnome_url_show, or using LD_PRELOAD with a custom .so designed to emulate gnome_url_show (and potentially the other GTK2 symbols) and pass it onto xdg-open.

From what I’ve seen older versions of Java have some ability to replace system classes that the newer versions don’t have, and whilst editing the apps bytecode itself is possible too, it’s not exactly elegant and only works on singular apps.

I can try dedicate some time soon into the LD_PRELOAD route since it effects me as well and presumably all Java snaps.

I wouldn’t worry about the Gtk-Messages at the end there, they’re common place in a lot of Snaps and are noise you can avoid worrying about in 99% of scenarios.

1 Like

Thanks, I think that I will fix it by documenting manual document open :slight_smile: Not a big deal.

I’ve worked on the LD_PRELOAD route anyway and it works for me as long as you’re using GTK2 exclusively. From the error output above, this might be able to help you.

I’ve not been able to get this to work in GTK3 and think overall this is something better done at either the GVFS/GIO or Java level itself, but I can confirm that the example Java code above works with this patch setup.

TLDR: setting GTK_USE_PORTAL=1 in the environment will probably get your application to work.

The gnome_url_show function mentioned here ends up calling GTK’s gtk_show_uri, which in turn calls GIO’s g_app_info_launch_default_for_uri:

This uses the freedesktop.org mime-apps spec to determine what application to launch. Inside the snap sandbox there is no application registered to handle PDF files, so the open fails.

There is a way to get this to work though if we enable GTK/GLib’s xdg-desktop-portal support. This is not currently enabled by default for snap applications, but can be done by setting the GTK_USE_PORTAL environment variable. In this mode, if g_app_info_launch_default_for_uri cannot find a handler for the given file or URI, it will ask the xdg-desktop-portal D-Bus service to open the file on its behalf outside of the sandbox.

This of course requires that xdg-desktop-portal be installed on the user’s system, but that is fairly common these days.

I tried export GTK_USE_PORTAL=1 with Java 11, with both GTK2 Snapcraft Desktop Helpers, and GTK3 with the gnome-3-28 extension.

In GTK2 the flag has no effect as you’d probably expect. In GTK3, the variable has no percievable effect, but that’s because both with and without the variable, GTK2 and GTK3 conflicts happen in the terminal complaining their symbols can’t occupy the same address space.

If I had to guess, it’s as a result of upstream Java code here:

Is this something that you think is resolvable without recompiling Java? There’s no GTK2/GTK3 crossover outside the confinement, so my niave assumption is that the extension does something that interferes in this specific context, but I’m not knowledgable enough to say what.

1 Like

The gnomevfs-2 library is an ancient GNOME 1.x library, which was obsolete in 2008. This is what preceded GIO/GVFS, so if you’re hitting that code path, something has gone terribly wrong.

It’s the GTK 2/3 code path that it should be hitting, in which case it’s the gtk_show_uri method that should matter. For both GTK 2 and GTK 3, these call through to GLib’s g_app_info_launch_default_for_uri:

https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-2-24/gtk/gtkshow.c#L75
https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gtk/gtkshow.c#L71

Both GTK versions link with GLib 2.x, so should be able to make the xdg-desktop-portal call provided it isn’t an ancient version of GLib.

If I add export GTK_USE_PORTAL=1 to line 67 https://github.com/bademux/emikrofirma-snap/blob/master/snap/snapcraft.yaml I have no java.io.IOException mentioned above, but still no pdf opened.

Do you get anything interesting printed to stderr or in the dmesg log when it fails to open the PDF?

Also: do you have xdg-desktop-portal and xdg-desktop-portal-gtk (or xdg-desktop-portal-kde if you’re using KDE) installed?

Can’t find anything interesting in dmesg and logs. I updated snapcraft with GTK_USE_PORTAL and related dependencies snapcraft.yaml

One thing I notice from your YAML is that you include both the Snapcraft GLIB part and also the Gnome 3-34 extension. This is generally undefined behaviour and something that might introduce some subtle behavioural differences. This is because both the GLib helper and Gnome extension have a desktop-launch script, and you’re effectively calling it twice and potentially ambiguously to which actual one is being called. They’re designed to be used exclusively.

I can’t promise it’ll help anything here, but I would recommend removing the GLib part and the desktop-launch prefix in the command: line. You should hopefully not notice any major changes, but it might subtly change some behaviours including potentially what’s going on here. It’ll also likely give a speed boost of a second or two at launch.

The reason this works technically is because the Gnome extension will actually modify your YAML as it’s being interpretted, and calls desktop-launch itself prior to running the command anyway, via command-chain functionality.

2 Likes

Thanks for hint! I clean up snapcraft.yaml applying your suggestions. Definitely it looks cleaner now, but file-open still doesn’t work.