diff --git a/src/main/java/xyz/orbitary/perigee/transport/EndpointResolver.java b/src/main/java/xyz/orbitary/perigee/transport/EndpointResolver.java index c1ae2cf..67d02cf 100644 --- a/src/main/java/xyz/orbitary/perigee/transport/EndpointResolver.java +++ b/src/main/java/xyz/orbitary/perigee/transport/EndpointResolver.java @@ -7,11 +7,15 @@ package xyz.orbitary.perigee.transport; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Stream; /** @@ -52,6 +56,7 @@ public static List resolve(boolean windows, Map env, Lis for (String sub : SANDBOX_SUBDIRS) { bases.add(withSeparator(dir) + sub + "/"); } + bases.addAll(flatpakRuntimeDirs(Path.of(dir, ".flatpak"))); } } bases.add("/tmp/"); @@ -83,4 +88,21 @@ private static String withSeparator(String dir) { return dir.endsWith("/") ? dir : dir + "/"; } + /** + * rather than littering SANDBOX_SUBDIRS with variations of + * ".flatpak/dev.vencord.Vesktop/xdg-run" + * for every client under the sun, find them all at once. + */ + private static List flatpakRuntimeDirs(Path flatpakDir) { + try (Stream apps = Files.list(flatpakDir)) { + return apps.map(app -> app.resolve("xdg-run")) + .filter(Files::isDirectory) + .map(path -> path + "/") + .sorted() + .toList(); + } catch (IOException | SecurityException e) { + return List.of(); + } + } + } diff --git a/src/main/java/xyz/orbitary/perigee/transport/TransportConnector.java b/src/main/java/xyz/orbitary/perigee/transport/TransportConnector.java index 33486ee..1ce73ed 100644 --- a/src/main/java/xyz/orbitary/perigee/transport/TransportConnector.java +++ b/src/main/java/xyz/orbitary/perigee/transport/TransportConnector.java @@ -23,7 +23,7 @@ public static Transport connect(List endpoints, boolean windows) throws try { return windows ? WindowsPipeTransport.connect(endpoint) : UnixSocketTransport.connect(endpoint); } catch (IOException | RuntimeException e) { - failure.addSuppressed(e); + failure.addSuppressed(new IOException(endpoint + ": " + e, e)); } } throw failure; diff --git a/src/test/java/xyz/orbitary/perigee/LiveDiscordTest.java b/src/test/java/xyz/orbitary/perigee/LiveDiscordTest.java index e564821..7ee2db4 100644 --- a/src/test/java/xyz/orbitary/perigee/LiveDiscordTest.java +++ b/src/test/java/xyz/orbitary/perigee/LiveDiscordTest.java @@ -74,7 +74,7 @@ void reportsHowDiscordTreatsEachActivityType() throws Exception { System.out.println("[live] " + type + " (documented rpcSupported=" + type.rpcSupported() + ") -> " + outcome); Thread.sleep(1_000); } - client.clearActivity().get(10, TimeUnit.SECONDS); + client.clearActivity().get(30, TimeUnit.SECONDS); } } diff --git a/src/test/java/xyz/orbitary/perigee/transport/EndpointResolverTest.java b/src/test/java/xyz/orbitary/perigee/transport/EndpointResolverTest.java index fc66c02..6dfa65b 100644 --- a/src/test/java/xyz/orbitary/perigee/transport/EndpointResolverTest.java +++ b/src/test/java/xyz/orbitary/perigee/transport/EndpointResolverTest.java @@ -8,10 +8,14 @@ package xyz.orbitary.perigee.transport; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -33,7 +37,7 @@ void windowsUsesNamedPipesAndIgnoresTheEnvironment() { @Test void unixFollowsDocumentedOrderWithSandboxesAndFallback() { - Map env = Map.of("XDG_RUNTIME_DIR", "/run/user/1000", "TMPDIR", "/var/tmp/", "TEMP", "/run/user/1000"); + Map env = Map.of("XDG_RUNTIME_DIR", "/run/user/1", "TMPDIR", "/var/tmp/", "TEMP", "/run/user/1"); List endpoints = EndpointResolver.resolve(false, env, List.of("/custom")); @@ -41,13 +45,13 @@ void unixFollowsDocumentedOrderWithSandboxesAndFallback() { assertEquals( List.of( "/custom/discord-ipc-0", - "/run/user/1000/discord-ipc-0", - "/run/user/1000/app/com.discordapp.Discord/discord-ipc-0", - "/run/user/1000/snap.discord/discord-ipc-0", - "/run/user/1000/app/com.discordapp.DiscordPTB/discord-ipc-0", - "/run/user/1000/snap.discord-ptb/discord-ipc-0", - "/run/user/1000/app/com.discordapp.DiscordCanary/discord-ipc-0", - "/run/user/1000/snap.discord-canary/discord-ipc-0", + "/run/user/1/discord-ipc-0", + "/run/user/1/app/com.discordapp.Discord/discord-ipc-0", + "/run/user/1/snap.discord/discord-ipc-0", + "/run/user/1/app/com.discordapp.DiscordPTB/discord-ipc-0", + "/run/user/1/snap.discord-ptb/discord-ipc-0", + "/run/user/1/app/com.discordapp.DiscordCanary/discord-ipc-0", + "/run/user/1/snap.discord-canary/discord-ipc-0", "/var/tmp/discord-ipc-0", "/tmp/discord-ipc-0" ), firstOfEach @@ -109,6 +113,18 @@ void ptbAndCanaryInstallsAreSearchedInsideTheirSandboxes() { } } + @Test + void flatpakClientsAreFoundInsideTheirXdgRunFolders(@TempDir Path runtime) throws IOException { + Files.createDirectories(runtime.resolve(".flatpak/dev.vencord.Vesktop/xdg-run")); + Files.createDirectories(runtime.resolve(".flatpak/123456")); + + List endpoints = EndpointResolver.resolve(false, Map.of("XDG_RUNTIME_DIR", runtime.toString()), List.of()); + + int vesktop = endpoints.indexOf(runtime + "/.flatpak/dev.vencord.Vesktop/xdg-run/discord-ipc-0"); + assertTrue(vesktop > endpoints.indexOf(runtime + "/snap.discord-canary/discord-ipc-0"), "after the official sandboxes"); + assertTrue(endpoints.stream().noneMatch(path -> path.contains(".flatpak/123456")), "instance folders without xdg-run are skipped"); + } + static Stream macOsEnvironments() { return Stream.of( Arguments.of("TMPDIR only", Map.of("TMPDIR", "/var/folders/ab/cd/T/"), "/var/folders/ab/cd/T/discord-ipc-0", 20), diff --git a/src/test/java/xyz/orbitary/perigee/transport/UnixSocketTransportTest.java b/src/test/java/xyz/orbitary/perigee/transport/UnixSocketTransportTest.java index 0a83f36..6aa9702 100644 --- a/src/test/java/xyz/orbitary/perigee/transport/UnixSocketTransportTest.java +++ b/src/test/java/xyz/orbitary/perigee/transport/UnixSocketTransportTest.java @@ -86,6 +86,8 @@ void theConnectorReportsEveryFailureWhenNothingIsListening() { IOException e = assertThrows(IOException.class, () -> TransportConnector.connect(List.of(dir.resolve("a").toString(), dir.resolve("b").toString()), false)); assertEquals(2, e.getSuppressed().length); + assertTrue(String.valueOf(e.getSuppressed()[0].getMessage()).startsWith(dir.resolve("a") + ": ")); + assertTrue(String.valueOf(e.getSuppressed()[1].getMessage()).startsWith(dir.resolve("b") + ": ")); } @Test