Skip to content

Commit f2881b8

Browse files
committed
first impl draft
1 parent 7b72518 commit f2881b8

File tree

5 files changed

+116
-1
lines changed

5 files changed

+116
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ Linux-specific implemenations of the [integrations-api](https://github.com/crypt
55

66
This project uses the following JVM properties:
77
* `cryptomator.integrationsLinux.trayIconsDir` - specifies the directory from which svg images for the tray icon are loaded
8-
8+
* `cryptomator.integrationsLinux.autoStartCmd` - specifies the command used for starting Cryptomator

src/main/java/module-info.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import org.cryptomator.integrations.autostart.AutoStartProvider;
12
import org.cryptomator.integrations.keychain.KeychainAccessProvider;
23
import org.cryptomator.integrations.revealpath.RevealPathService;
34
import org.cryptomator.integrations.tray.TrayMenuController;
5+
import org.cryptomator.linux.autostart.FreedesktopAutoStartService;
46
import org.cryptomator.linux.keychain.KDEWalletKeychainAccess;
57
import org.cryptomator.linux.keychain.SecretServiceKeychainAccess;
68
import org.cryptomator.linux.revealpath.DBusSendRevealPathService;
@@ -14,6 +16,7 @@
1416
requires org.purejava.kwallet;
1517
requires de.swiesend.secretservice;
1618

19+
provides AutoStartProvider with FreedesktopAutoStartService;
1720
provides KeychainAccessProvider with SecretServiceKeychainAccess, KDEWalletKeychainAccess;
1821
provides RevealPathService with DBusSendRevealPathService;
1922
provides TrayMenuController with AppindicatorTrayMenuController;
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package org.cryptomator.linux.autostart;
2+
3+
import org.cryptomator.integrations.autostart.AutoStartProvider;
4+
import org.cryptomator.integrations.autostart.ToggleAutoStartFailedException;
5+
import org.cryptomator.integrations.common.CheckAvailability;
6+
import org.cryptomator.integrations.common.OperatingSystem;
7+
import org.slf4j.Logger;
8+
import org.slf4j.LoggerFactory;
9+
10+
import java.io.IOException;
11+
import java.nio.file.Files;
12+
import java.nio.file.Path;
13+
import java.nio.file.StandardOpenOption;
14+
import java.util.Objects;
15+
16+
/**
17+
* Enables autostart for Linux desktop environments following the freedesktop standard.
18+
* <p>
19+
* This service is based on <a href=https://specifications.freedesktop.org/autostart-spec/autostart-spec-0.5.html>version 0.5 of the freedesktop autostart-spec</a>.
20+
*/
21+
@CheckAvailability
22+
@OperatingSystem(OperatingSystem.Value.LINUX)
23+
public class FreedesktopAutoStartService implements AutoStartProvider {
24+
25+
private static final Logger LOG = LoggerFactory.getLogger(FreedesktopAutoStartService.class);
26+
private static final String CMD_PROPERTY = "cryptomator.integrationsLinux.autoStartCmd";
27+
private static final String AUTOSTART_FILENAME = "Cryptomator.desktop";
28+
private static final String CONTENT_TEMPLATE = """
29+
[Desktop Entry]
30+
Type=Application
31+
Exec=%s
32+
Hidden=false
33+
NoDisplay=false
34+
X-GNOME-Autostart-enabled=true
35+
Name=Cryptomator
36+
Comment=Created with %s
37+
""";
38+
39+
private final Path autostartFile;
40+
private final String content;
41+
42+
public FreedesktopAutoStartService() {
43+
var xdgConfigDirString = Objects.requireNonNullElse(System.getenv("XDG_CONFIG_HOME"), System.getProperty("user.home") + "/.config");
44+
this.autostartFile = Path.of(xdgConfigDirString, "autostart", AUTOSTART_FILENAME);
45+
46+
var execValue = System.getProperty(CMD_PROPERTY);
47+
if (execValue == null) {
48+
LOG.debug("Property {} not set, using command path", CMD_PROPERTY);
49+
execValue = ProcessHandle.current().info().command().orElse("");
50+
}
51+
this.content = CONTENT_TEMPLATE.formatted(execValue, this.getClass().getName());
52+
}
53+
54+
@Override
55+
public void enable() throws ToggleAutoStartFailedException {
56+
try {
57+
Files.writeString(autostartFile, content, StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
58+
} catch (IOException e) {
59+
throw new ToggleAutoStartFailedException("Failed to activate Cryptomator autostart for GNOME desktop environment.", e);
60+
}
61+
}
62+
63+
@Override
64+
public void disable() throws ToggleAutoStartFailedException {
65+
try {
66+
Files.deleteIfExists(autostartFile);
67+
} catch (IOException e) {
68+
throw new ToggleAutoStartFailedException("Failed to deactivate Cryptomator autostart for GNOME desktop environment.", e);
69+
}
70+
}
71+
72+
@Override
73+
public boolean isEnabled() {
74+
return Files.exists(autostartFile);
75+
}
76+
77+
@CheckAvailability
78+
public boolean isSupported() {
79+
//TODO: might need to research which Desktop Environments support this
80+
return Files.exists(autostartFile.getParent());
81+
}
82+
83+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
org.cryptomator.linux.autostart.FreedesktopAutoStartService
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package org.cryptomator.linux.autostart;
2+
3+
import org.junit.jupiter.api.Assertions;
4+
import org.junit.jupiter.api.MethodOrderer;
5+
import org.junit.jupiter.api.Order;
6+
import org.junit.jupiter.api.Test;
7+
import org.junit.jupiter.api.TestMethodOrder;
8+
9+
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
10+
public class FreeDesktopAutoStartIT {
11+
12+
FreedesktopAutoStartService inTest = new FreedesktopAutoStartService();
13+
14+
@Test
15+
@Order(1)
16+
public void testAutostartEnable() {
17+
Assertions.assertDoesNotThrow(() -> inTest.enable());
18+
Assertions.assertTrue(inTest.isEnabled());
19+
}
20+
21+
22+
@Test
23+
@Order(2)
24+
public void testAutostartDisable() {
25+
Assertions.assertDoesNotThrow(() -> inTest.disable());
26+
Assertions.assertFalse(inTest.isEnabled());
27+
}
28+
}

0 commit comments

Comments
 (0)