Skip to content

Commit

Permalink
Merge pull request #16 from cryptomator/feature/reveal-path-service
Browse files Browse the repository at this point in the history
Feature: RevealPathService via dbus freedesktop FileManger interface
  • Loading branch information
infeo authored Jan 17, 2023
2 parents 80f7770 + d35878e commit 0c6662e
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 1 deletion.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
<project.jdk.version>17</project.jdk.version>

<!-- runtime dependencies -->
<api.version>1.1.0</api.version>
<api.version>1.2.0-beta4</api.version>
<secret-service.version>1.7.0</secret-service.version>
<kdewallet.version>1.2.6</kdewallet.version>
<guava.version>31.1-jre</guava.version>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package org.cryptomator.linux.revealpath;

import org.cryptomator.integrations.revealpath.RevealFailedException;
import org.cryptomator.integrations.revealpath.RevealPathService;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

public class DBusFileMangerRevealPath implements RevealPathService {

private static final String FOR_FOLDERS = "org.freedesktop.FileManager1.ShowFolders";
private static final String FOR_FILES = "org.freedesktop.FileManager1.ShowItems";
private static final int TIMEOUT_THRESHOLD=5000;

@Override
public void reveal(Path path) throws RevealFailedException {
try {
var attrs = Files.readAttributes(path, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
var uriPath = Arrays.stream(path.toUri().getPath().split("/")).map(s -> URLEncoder.encode(s, StandardCharsets.UTF_8).replace("+", "%20")).collect(Collectors.joining("/"));
ProcessBuilder pb = new ProcessBuilder().command("dbus-send",
"--print-reply",
"--reply-timeout="+TIMEOUT_THRESHOLD,
"--dest=org.freedesktop.FileManager1",
"--type=method_call",
"/org/freedesktop/FileManager1",
attrs.isDirectory() ? FOR_FOLDERS : FOR_FILES,
String.format("array:string:file://%s", uriPath),
"string:\"\""
);
var process = pb.start();
if (process.waitFor(TIMEOUT_THRESHOLD, TimeUnit.MILLISECONDS)) {
int exitValue = process.exitValue();
if (exitValue != 0) {
throw new RevealFailedException("dbus-send returned with code" + exitValue);
}
}
} catch (IOException e) {
throw new RevealFailedException(e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RevealFailedException(e);
}
}

@Override
public boolean isSupported() {
CountDownLatch waitBarrier = new CountDownLatch(3);
ProcessBuilder builderExistsDbusSend = new ProcessBuilder().command("which", "dbus-send");
ProcessBuilder builderExistsNautilus = new ProcessBuilder().command("which", "nautilus");
ProcessBuilder builderExistsDolphin = new ProcessBuilder().command("which", "dolphin");
try {
var existsDbusSend = builderExistsDbusSend.start();
existsDbusSend.onExit().thenRun(waitBarrier::countDown);
var existsNautilus = builderExistsNautilus.start();
existsNautilus.onExit().thenRun(waitBarrier::countDown);
var existsDolphin = builderExistsDolphin.start();
existsDolphin.onExit().thenRun(waitBarrier::countDown);
if (waitBarrier.await(TIMEOUT_THRESHOLD, TimeUnit.MILLISECONDS)) {
return existsDbusSend.exitValue() == 0 && (existsNautilus.exitValue() == 0 | existsDolphin.exitValue() == 0);
}
} catch (IOException | InterruptedException e) {
//NO-OP
}
return false;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.cryptomator.linux.revealpath.DBusFileMangerRevealPath
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.cryptomator.linux.keychain;

import org.cryptomator.integrations.revealpath.RevealFailedException;
import org.cryptomator.linux.revealpath.DBusFileMangerRevealPath;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.api.io.TempDir;

import java.nio.file.Path;

@EnabledOnOs(OS.LINUX)
@Disabled
public class DbusFileManagerRevealPathTest {

@TempDir Path tmpDir;
DBusFileMangerRevealPath inTest = new DBusFileMangerRevealPath();

@Test
public void testIsSupported() {
Assertions.assertDoesNotThrow(() -> inTest.isSupported());
}

@Test
public void testRevealSuccess() {
DBusFileMangerRevealPath revealPathService = new DBusFileMangerRevealPath();
Assumptions.assumeTrue(revealPathService.isSupported());

Assertions.assertDoesNotThrow(() -> revealPathService.reveal(tmpDir));
}

@Test
public void testRevealFail() {
DBusFileMangerRevealPath revealPathService = new DBusFileMangerRevealPath();
Assumptions.assumeTrue(revealPathService.isSupported());

Assertions.assertThrows(RevealFailedException.class, () -> revealPathService.reveal(tmpDir.resolve("foobar")));
}
}

0 comments on commit 0c6662e

Please sign in to comment.