Преглед на файлове

Merge branch 'feature/mount-method-settings' into develop

Sebastian Stenzel преди 9 години
родител
ревизия
1a75f23081
променени са 21 файла, в които са добавени 245 реда и са изтрити 154 реда
  1. 6 1
      main/frontend-api/src/main/java/org/cryptomator/frontend/Frontend.java
  2. 1 1
      main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavFrontend.java
  3. 11 0
      main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavModule.java
  4. 1 1
      main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/FallbackWebDavMounter.java
  5. 94 0
      main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/LinuxGvfsDavMounter.java
  6. 5 11
      main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/LinuxGvfsWebDavMounter.java
  7. 1 1
      main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXAppleScriptWebDavMounter.java
  8. 1 1
      main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXShellScriptWebDavMounter.java
  9. 0 105
      main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MountStrategies.java
  10. 31 0
      main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WebDavMounterModule.java
  11. 15 14
      main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WebDavMounterProvider.java
  12. 6 1
      main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WebDavMounterStrategy.java
  13. 4 4
      main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsWebDavMounter.java
  14. 1 3
      main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavComponent.java
  15. 2 9
      main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java
  16. 18 0
      main/ui/src/main/java/org/cryptomator/ui/controllers/SettingsController.java
  17. 2 1
      main/ui/src/main/java/org/cryptomator/ui/model/Vault.java
  18. 13 1
      main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java
  19. 26 0
      main/ui/src/main/resources/css/linux_theme.css
  20. 6 0
      main/ui/src/main/resources/fxml/settings.fxml
  21. 1 0
      main/ui/src/main/resources/localization/en.txt

+ 6 - 1
main/frontend-api/src/main/java/org/cryptomator/frontend/Frontend.java

@@ -14,7 +14,12 @@ import java.util.Optional;
 public interface Frontend extends AutoCloseable {
 
 	public enum MountParam {
-		MOUNT_NAME, HOSTNAME, WIN_DRIVE_LETTER
+		MOUNT_NAME, HOSTNAME, WIN_DRIVE_LETTER,
+
+		/**
+		 * "dav" or "webdav"
+		 */
+		PREFERRED_GVFS_SCHEME
 	}
 
 	void mount(Map<MountParam, Optional<String>> map) throws CommandFailedException;

+ 1 - 1
main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavFrontend.java

@@ -45,7 +45,7 @@ class WebDavFrontend implements Frontend {
 
 	@Override
 	public void mount(Map<MountParam, Optional<String>> mountParams) throws CommandFailedException {
-		mount = webdavMounterProvider.get().mount(uri, mountParams);
+		mount = webdavMounterProvider.chooseMounter(mountParams).mount(uri, mountParams);
 	}
 
 	@Override

+ 11 - 0
main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavModule.java

@@ -0,0 +1,11 @@
+package org.cryptomator.frontend.webdav;
+
+import org.cryptomator.common.CommonsModule;
+import org.cryptomator.frontend.webdav.mount.WebDavMounterModule;
+
+import dagger.Module;
+
+@Module(includes = {CommonsModule.class, WebDavMounterModule.class})
+public class WebDavModule {
+
+}

+ 1 - 1
main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/FallbackWebDavMounter.java

@@ -23,7 +23,7 @@ import org.cryptomator.frontend.Frontend.MountParam;
 final class FallbackWebDavMounter implements WebDavMounterStrategy {
 
 	@Override
-	public boolean shouldWork() {
+	public boolean shouldWork(Map<MountParam, Optional<String>> mountParams) {
 		return true;
 	}
 

+ 94 - 0
main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/LinuxGvfsDavMounter.java

@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2016 Sebastian Stenzel, Markus Kreusch
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ * 
+ * Contributors:
+ *     Sebastian Stenzel - initial API and implementation
+ *     Markus Kreusch - Refactored WebDavMounter to use strategy pattern
+ *     Mohit Raju - Added fallback schema-name "webdav" when opening file managers
+ ******************************************************************************/
+package org.cryptomator.frontend.webdav.mount;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.Optional;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.apache.commons.lang3.SystemUtils;
+import org.cryptomator.frontend.CommandFailedException;
+import org.cryptomator.frontend.Frontend.MountParam;
+import org.cryptomator.frontend.webdav.mount.command.Script;
+
+@Singleton
+final class LinuxGvfsDavMounter implements WebDavMounterStrategy {
+
+	@Inject
+	LinuxGvfsDavMounter() {
+	}
+
+	@Override
+	public boolean shouldWork(Map<MountParam, Optional<String>> mountParams) {
+		if (SystemUtils.IS_OS_LINUX) {
+			Optional<String> prefScheme = mountParams.getOrDefault(MountParam.PREFERRED_GVFS_SCHEME, Optional.empty());
+			boolean prefSchemeIsUnspecifiedOrDav = !prefScheme.isPresent() || prefScheme.get().equalsIgnoreCase("dav");
+			final Script checkScripts = Script.fromLines("which gvfs-mount xdg-open");
+			try {
+				checkScripts.execute();
+				return prefSchemeIsUnspecifiedOrDav;
+			} catch (CommandFailedException e) {
+				return false;
+			}
+		} else {
+			return false;
+		}
+	}
+
+	@Override
+	public void warmUp(int serverPort) {
+		// no-op
+	}
+
+	@Override
+	public WebDavMount mount(URI uri, Map<MountParam, Optional<String>> mountParams) throws CommandFailedException {
+		final Script mountScript = Script.fromLines("set -x", "gvfs-mount \"dav:$DAV_SSP\"").addEnv("DAV_SSP", uri.getRawSchemeSpecificPart());
+		mountScript.execute();
+		return new LinuxGvfsDavMount(uri);
+	}
+
+	private static class LinuxGvfsDavMount extends AbstractWebDavMount {
+		private final URI webDavUri;
+		private final Script testMountStillExistsScript;
+		private final Script unmountScript;
+
+		private LinuxGvfsDavMount(URI webDavUri) {
+			this.webDavUri = webDavUri;
+			this.testMountStillExistsScript = Script.fromLines("set -x", "test `gvfs-mount --list | grep \"$DAV_SSP\" | wc -l` -eq 1").addEnv("DAV_SSP", webDavUri.getRawSchemeSpecificPart());
+			this.unmountScript = Script.fromLines("set -x", "gvfs-mount -u \"dav:$DAV_SSP\"").addEnv("DAV_SSP", webDavUri.getRawSchemeSpecificPart());
+		}
+
+		@Override
+		public void unmount() throws CommandFailedException {
+			boolean mountStillExists;
+			try {
+				testMountStillExistsScript.execute();
+				mountStillExists = true;
+			} catch (CommandFailedException e) {
+				mountStillExists = false;
+			}
+			// only attempt unmount if user didn't unmount manually:
+			if (mountStillExists) {
+				unmountScript.execute();
+			}
+		}
+
+		@Override
+		public void reveal() throws CommandFailedException {
+			Script.fromLines("set -x", "xdg-open \"webdav:$DAV_SSP\"").addEnv("DAV_SSP", webDavUri.getRawSchemeSpecificPart()).execute();
+		}
+
+	}
+
+}

+ 5 - 11
main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/LinuxGvfsWebDavMounter.java

@@ -30,12 +30,14 @@ final class LinuxGvfsWebDavMounter implements WebDavMounterStrategy {
 	}
 
 	@Override
-	public boolean shouldWork() {
+	public boolean shouldWork(Map<MountParam, Optional<String>> mountParams) {
 		if (SystemUtils.IS_OS_LINUX) {
+			Optional<String> prefScheme = mountParams.getOrDefault(MountParam.PREFERRED_GVFS_SCHEME, Optional.empty());
+			boolean prefSchemeIsUnspecifiedOrWebDav = !prefScheme.isPresent() || prefScheme.get().equalsIgnoreCase("webdav");
 			final Script checkScripts = Script.fromLines("which gvfs-mount xdg-open");
 			try {
 				checkScripts.execute();
-				return true;
+				return prefSchemeIsUnspecifiedOrWebDav;
 			} catch (CommandFailedException e) {
 				return false;
 			}
@@ -84,15 +86,7 @@ final class LinuxGvfsWebDavMounter implements WebDavMounterStrategy {
 
 		@Override
 		public void reveal() throws CommandFailedException {
-			try {
-				openMountWithWebdavUri("dav:" + webDavUri.getRawSchemeSpecificPart()).execute();
-			} catch (CommandFailedException exception) {
-				openMountWithWebdavUri("webdav:" + webDavUri.getRawSchemeSpecificPart()).execute();
-			}
-		}
-
-		private Script openMountWithWebdavUri(String webdavUri) {
-			return Script.fromLines("set -x", "xdg-open \"$DAV_URI\"").addEnv("DAV_URI", webdavUri);
+			Script.fromLines("set -x", "xdg-open \"webdav:$DAV_SSP\"").addEnv("DAV_SSP", webDavUri.getRawSchemeSpecificPart()).execute();
 		}
 
 	}

+ 1 - 1
main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXAppleScriptWebDavMounter.java

@@ -38,7 +38,7 @@ final class MacOsXAppleScriptWebDavMounter implements WebDavMounterStrategy {
 	}
 
 	@Override
-	public boolean shouldWork() {
+	public boolean shouldWork(Map<MountParam, Optional<String>> mountParams) {
 		return SystemUtils.IS_OS_MAC_OSX && semVerComparator.compare(SystemUtils.OS_VERSION, "10.10") >= 0;
 	}
 

+ 1 - 1
main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MacOsXShellScriptWebDavMounter.java

@@ -37,7 +37,7 @@ final class MacOsXShellScriptWebDavMounter implements WebDavMounterStrategy {
 	}
 
 	@Override
-	public boolean shouldWork() {
+	public boolean shouldWork(Map<MountParam, Optional<String>> mountParams) {
 		return SystemUtils.IS_OS_MAC_OSX && semVerComparator.compare(SystemUtils.OS_VERSION, "10.10") < 0;
 	}
 

+ 0 - 105
main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/MountStrategies.java

@@ -1,105 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Sebastian Stenzel and others.
- * This file is licensed under the terms of the MIT license.
- * See the LICENSE.txt file for more info.
- *
- * Contributors:
- *     Sebastian Stenzel - initial API and implementation
- *******************************************************************************/
-package org.cryptomator.frontend.webdav.mount;
-
-import static java.util.Arrays.asList;
-import static java.util.Collections.unmodifiableList;
-
-import java.util.Collection;
-import java.util.Iterator;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-@Singleton
-class MountStrategies implements Collection<WebDavMounterStrategy> {
-
-	private final Collection<WebDavMounterStrategy> delegate;
-
-	@Inject
-	MountStrategies(LinuxGvfsWebDavMounter linuxMounter, MacOsXAppleScriptWebDavMounter osxAppleScriptMounter, MacOsXShellScriptWebDavMounter osxShellScriptMounter, WindowsWebDavMounter winMounter) {
-		delegate = unmodifiableList(asList(linuxMounter, osxAppleScriptMounter, osxShellScriptMounter, winMounter));
-	}
-
-	@Override
-	public int size() {
-		return delegate.size();
-	}
-
-	@Override
-	public boolean isEmpty() {
-		return delegate.isEmpty();
-	}
-
-	@Override
-	public boolean contains(Object o) {
-		return delegate.contains(o);
-	}
-
-	@Override
-	public Iterator<WebDavMounterStrategy> iterator() {
-		return delegate.iterator();
-	}
-
-	@Override
-	public Object[] toArray() {
-		return delegate.toArray();
-	}
-
-	@Override
-	public <T> T[] toArray(T[] a) {
-		return delegate.toArray(a);
-	}
-
-	@Override
-	public boolean add(WebDavMounterStrategy e) {
-		return delegate.add(e);
-	}
-
-	@Override
-	public boolean remove(Object o) {
-		return delegate.remove(o);
-	}
-
-	@Override
-	public boolean containsAll(Collection<?> c) {
-		return delegate.containsAll(c);
-	}
-
-	@Override
-	public boolean addAll(Collection<? extends WebDavMounterStrategy> c) {
-		return delegate.addAll(c);
-	}
-
-	@Override
-	public boolean removeAll(Collection<?> c) {
-		return delegate.removeAll(c);
-	}
-
-	@Override
-	public boolean retainAll(Collection<?> c) {
-		return delegate.retainAll(c);
-	}
-
-	@Override
-	public void clear() {
-		delegate.clear();
-	}
-
-	@Override
-	public boolean equals(Object o) {
-		return delegate.equals(o);
-	}
-
-	@Override
-	public int hashCode() {
-		return delegate.hashCode();
-	}
-
-}

+ 31 - 0
main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WebDavMounterModule.java

@@ -0,0 +1,31 @@
+package org.cryptomator.frontend.webdav.mount;
+
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import com.google.common.collect.Sets;
+
+import dagger.Module;
+import dagger.Provides;
+import dagger.multibindings.ElementsIntoSet;
+
+@Module
+public class WebDavMounterModule {
+
+	@Provides
+	@ElementsIntoSet
+	static Set<WebDavMounterStrategy> provideMounters(LinuxGvfsWebDavMounter linuxWebDavMounter, LinuxGvfsDavMounter linuxDavMounter, MacOsXAppleScriptWebDavMounter osxAppleScriptMounter,
+			MacOsXShellScriptWebDavMounter osxShellScriptMounter, WindowsWebDavMounter winMounter) {
+		return Sets.newHashSet(linuxWebDavMounter, linuxDavMounter, osxAppleScriptMounter, osxShellScriptMounter, winMounter);
+	}
+
+	@Provides
+	@Singleton
+	@Named("fallback")
+	static WebDavMounterStrategy provideFallbackStrategy() {
+		return new FallbackWebDavMounter();
+	}
+
+}

+ 15 - 14
main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WebDavMounterProvider.java

@@ -10,34 +10,35 @@
 package org.cryptomator.frontend.webdav.mount;
 
 import java.util.Collection;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
 
 import javax.inject.Inject;
-import javax.inject.Provider;
+import javax.inject.Named;
 import javax.inject.Singleton;
 
+import org.cryptomator.frontend.Frontend.MountParam;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @Singleton
-public class WebDavMounterProvider implements Provider<WebDavMounter> {
+public class WebDavMounterProvider {
 
 	private static final Logger LOG = LoggerFactory.getLogger(WebDavMounterProvider.class);
-	private final WebDavMounterStrategy choosenStrategy;
+	private final Collection<WebDavMounterStrategy> availableStrategies;
+	private final WebDavMounterStrategy fallbackStrategy;
 
 	@Inject
-	public WebDavMounterProvider(MountStrategies availableStrategies) {
-		this.choosenStrategy = getStrategyWhichShouldWork(availableStrategies);
+	public WebDavMounterProvider(Set<WebDavMounterStrategy> availableStrategies, @Named("fallback") WebDavMounterStrategy fallbackStrategy) {
+		this.availableStrategies = availableStrategies;
+		this.fallbackStrategy = fallbackStrategy;
 	}
 
-	@Override
-	public WebDavMounter get() {
-		return this.choosenStrategy;
-	}
-
-	private WebDavMounterStrategy getStrategyWhichShouldWork(Collection<WebDavMounterStrategy> availableStrategies) {
-		WebDavMounterStrategy strategy = availableStrategies.stream().filter(WebDavMounterStrategy::shouldWork).findFirst().orElse(new FallbackWebDavMounter());
-		LOG.info("Using {}", strategy.getClass().getSimpleName());
-		return strategy;
+	public WebDavMounter chooseMounter(Map<MountParam, Optional<String>> mountParams) {
+		WebDavMounterStrategy result = availableStrategies.stream().filter(strategy -> strategy.shouldWork(mountParams)).findFirst().orElse(fallbackStrategy);
+		LOG.info("Using {}", result.getClass().getSimpleName());
+		return result;
 	}
 
 }

+ 6 - 1
main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WebDavMounterStrategy.java

@@ -9,6 +9,11 @@
  ******************************************************************************/
 package org.cryptomator.frontend.webdav.mount;
 
+import java.util.Map;
+import java.util.Optional;
+
+import org.cryptomator.frontend.Frontend.MountParam;
+
 /**
  * A strategy able to mount a webdav share and display it to the user.
  * 
@@ -19,7 +24,7 @@ interface WebDavMounterStrategy extends WebDavMounter {
 	/**
 	 * @return {@code false} if this {@code WebDavMounterStrategy} can not work on the local machine, {@code true} if it could work
 	 */
-	boolean shouldWork();
+	boolean shouldWork(Map<MountParam, Optional<String>> mountParams);
 
 	/**
 	 * Invoked when mounting strategy gets chosen. On some operating systems (we don't want to tell names here) mounting might be faster,

+ 4 - 4
main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/mount/WindowsWebDavMounter.java

@@ -61,7 +61,7 @@ final class WindowsWebDavMounter implements WebDavMounterStrategy {
 	}
 
 	@Override
-	public boolean shouldWork() {
+	public boolean shouldWork(Map<MountParam, Optional<String>> mountParams) {
 		return SystemUtils.IS_OS_WINDOWS;
 	}
 
@@ -102,7 +102,7 @@ final class WindowsWebDavMounter implements WebDavMounterStrategy {
 		mountScript.addEnv("DAV_UNC_PATH", uri.getRawPath().replace('/', '\\'));
 		return mountScript.execute(MOUNT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
 	}
-	
+
 	private void addProxyOverrides(URI uri) throws IOException, CommandFailedException {
 		try {
 			// get existing value for ProxyOverride key from reqistry:
@@ -110,7 +110,7 @@ final class WindowsWebDavMounter implements WebDavMounterStrategy {
 			Process queryCmd = query.start();
 			String queryStdOut = IOUtils.toString(queryCmd.getInputStream(), StandardCharsets.UTF_8);
 			int queryResult = queryCmd.waitFor();
-			
+
 			// determine new value for ProxyOverride key:
 			Set<String> overrides = new HashSet<>();
 			Matcher matcher = REG_QUERY_PROXY_OVERRIDES_PATTERN.matcher(queryStdOut);
@@ -122,7 +122,7 @@ final class WindowsWebDavMounter implements WebDavMounterStrategy {
 			overrides.add("<local>");
 			overrides.add(uri.getHost());
 			overrides.add(uri.getHost() + ":" + uri.getPort());
-			
+
 			// set new value:
 			String overridesStr = StringUtils.join(overrides, ';');
 			ProcessBuilder add = new ProcessBuilder("reg", "add", "\"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\"", "/v", "ProxyOverride", "/d", "\"" + overridesStr + "\"", "/f");

+ 1 - 3
main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavComponent.java

@@ -10,12 +10,10 @@ package org.cryptomator.frontend.webdav;
 
 import javax.inject.Singleton;
 
-import org.cryptomator.common.CommonsModule;
-
 import dagger.Component;
 
 @Singleton
-@Component(modules = {CommonsModule.class})
+@Component(modules = {WebDavModule.class})
 public interface WebDavComponent {
 
 	WebDavServer server();

+ 2 - 9
main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java

@@ -17,9 +17,8 @@ import javax.inject.Singleton;
 import org.cryptomator.common.CommonsModule;
 import org.cryptomator.crypto.engine.impl.CryptoEngineModule;
 import org.cryptomator.frontend.FrontendFactory;
+import org.cryptomator.frontend.webdav.WebDavModule;
 import org.cryptomator.frontend.webdav.WebDavServer;
-import org.cryptomator.frontend.webdav.mount.WebDavMounter;
-import org.cryptomator.frontend.webdav.mount.WebDavMounterProvider;
 import org.cryptomator.ui.model.VaultObjectMapperProvider;
 import org.cryptomator.ui.settings.Settings;
 import org.cryptomator.ui.settings.SettingsProvider;
@@ -32,7 +31,7 @@ import dagger.Provides;
 import javafx.application.Application;
 import javafx.stage.Stage;
 
-@Module(includes = {CryptoEngineModule.class, CommonsModule.class})
+@Module(includes = {CryptoEngineModule.class, CommonsModule.class, WebDavModule.class})
 class CryptomatorModule {
 
 	private final Application application;
@@ -83,12 +82,6 @@ class CryptomatorModule {
 		return closer.closeLater(Executors.newCachedThreadPool(), ExecutorService::shutdown).get().orElseThrow(IllegalStateException::new);
 	}
 
-	@Provides
-	@Singleton
-	WebDavMounter provideWebDavMounter(WebDavMounterProvider webDavMounterProvider) {
-		return webDavMounterProvider.get();
-	}
-
 	@Provides
 	@Singleton
 	FrontendFactory provideFrontendFactory(DeferredCloser closer, WebDavServer webDavServer, Settings settings) {

+ 18 - 0
main/ui/src/main/java/org/cryptomator/ui/controllers/SettingsController.java

@@ -22,6 +22,7 @@ import org.fxmisc.easybind.EasyBind;
 
 import javafx.fxml.FXML;
 import javafx.scene.control.CheckBox;
+import javafx.scene.control.ChoiceBox;
 import javafx.scene.control.Label;
 import javafx.scene.control.TextField;
 import javafx.scene.input.KeyEvent;
@@ -52,6 +53,12 @@ public class SettingsController extends LocalizedFXMLViewController {
 	@FXML
 	private Label versionLabel;
 
+	@FXML
+	private Label prefGvfsSchemeLabel;
+
+	@FXML
+	private ChoiceBox<String> prefGvfsScheme;
+
 	@Override
 	public void initialize() {
 		checkForUpdatesCheckbox.setDisable(areUpdatesManagedExternally());
@@ -62,10 +69,16 @@ public class SettingsController extends LocalizedFXMLViewController {
 		useIpv6Checkbox.setVisible(SystemUtils.IS_OS_WINDOWS);
 		useIpv6Checkbox.setSelected(SystemUtils.IS_OS_WINDOWS && settings.shouldUseIpv6());
 		versionLabel.setText(String.format(localization.getString("settings.version.label"), applicationVersion().orElse("SNAPSHOT")));
+		prefGvfsSchemeLabel.setVisible(SystemUtils.IS_OS_LINUX);
+		prefGvfsScheme.setVisible(SystemUtils.IS_OS_LINUX);
+		prefGvfsScheme.getItems().add("dav");
+		prefGvfsScheme.getItems().add("webdav");
+		prefGvfsScheme.setValue(settings.getPreferredGvfsScheme());
 
 		EasyBind.subscribe(checkForUpdatesCheckbox.selectedProperty(), this::checkForUpdateDidChange);
 		EasyBind.subscribe(portField.textProperty(), this::portDidChange);
 		EasyBind.subscribe(useIpv6Checkbox.selectedProperty(), this::useIpv6DidChange);
+		EasyBind.subscribe(prefGvfsScheme.valueProperty(), this::prefGvfsSchemeDidChange);
 	}
 
 	@Override
@@ -101,6 +114,11 @@ public class SettingsController extends LocalizedFXMLViewController {
 		settings.save();
 	}
 
+	private void prefGvfsSchemeDidChange(String newValue) {
+		settings.setPreferredGvfsScheme(newValue);
+		settings.save();
+	}
+
 	private void filterNumericKeyEvents(KeyEvent t) {
 		if (t.getCharacter() == null || t.getCharacter().length() == 0) {
 			return;

+ 2 - 1
main/ui/src/main/java/org/cryptomator/ui/model/Vault.java

@@ -154,7 +154,8 @@ public class Vault implements CryptoFileSystemDelegate {
 		return ImmutableMap.of( //
 				MountParam.MOUNT_NAME, Optional.ofNullable(mountName), //
 				MountParam.WIN_DRIVE_LETTER, Optional.ofNullable(CharUtils.toString(winDriveLetter)), //
-				MountParam.HOSTNAME, Optional.of(hostname) //
+				MountParam.HOSTNAME, Optional.of(hostname), //
+				MountParam.PREFERRED_GVFS_SCHEME, Optional.ofNullable(settings.getPreferredGvfsScheme()) //
 		);
 	}
 

+ 13 - 1
main/ui/src/main/java/org/cryptomator/ui/settings/Settings.java

@@ -18,7 +18,7 @@ import org.cryptomator.ui.model.Vault;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 
-@JsonPropertyOrder(value = {"directories", "checkForUpdatesEnabled", "port", "useIpv6", "numTrayNotifications"})
+@JsonPropertyOrder(value = {"directories", "checkForUpdatesEnabled", "port", "useIpv6", "numTrayNotifications", "preferredGvfsScheme"})
 public class Settings implements Serializable {
 
 	private static final long serialVersionUID = 7609959894417878744L;
@@ -27,6 +27,7 @@ public class Settings implements Serializable {
 	public static final int DEFAULT_PORT = 42427;
 	public static final boolean DEFAULT_USE_IPV6 = false;
 	public static final Integer DEFAULT_NUM_TRAY_NOTIFICATIONS = 3;
+	public static final String DEFAULT_GVFS_SCHEME = "dav";
 
 	private final Consumer<Settings> saveCmd;
 
@@ -45,6 +46,9 @@ public class Settings implements Serializable {
 	@JsonProperty("numTrayNotifications")
 	private Integer numTrayNotifications;
 
+	@JsonProperty("preferredGvfsScheme")
+	private String preferredGvfsScheme;
+
 	/**
 	 * Package-private constructor; use {@link SettingsProvider}.
 	 */
@@ -113,4 +117,12 @@ public class Settings implements Serializable {
 		this.numTrayNotifications = numTrayNotifications;
 	}
 
+	public String getPreferredGvfsScheme() {
+		return preferredGvfsScheme == null ? DEFAULT_GVFS_SCHEME : preferredGvfsScheme;
+	}
+
+	public void setPreferredGvfsScheme(String preferredGvfsScheme) {
+		this.preferredGvfsScheme = preferredGvfsScheme;
+	}
+
 }

+ 26 - 0
main/ui/src/main/resources/css/linux_theme.css

@@ -325,6 +325,32 @@
 	-fx-background-color: COLOR_TEXT;
 }
 
+/*******************************************************************************
+ *                                                                             *
+ * ChoiceBox                                                                   *
+ *                                                                             *
+ ******************************************************************************/
+
+.choice-box {
+	-fx-background-color: COLOR_BORDER_DARK, COLOR_BACKGROUND;
+	-fx-background-insets: 0, 1;
+	-fx-background-radius: 0, 0;
+	-fx-padding: 0.1em 0.6em 0.1em 0.6em;
+	-fx-text-fill: COLOR_TEXT;
+}
+
+.choice-box > .open-button > .arrow {
+	-fx-background-color: transparent, COLOR_TEXT;
+	-fx-background-insets: 0 0 -1 0, 0;
+	-fx-padding: 0.166667em 0.333333em 0.166667em 0.333333em; /* 2 4 2 4 */
+	-fx-shape: "M 0 0 h 7 l -3.5 4 z";
+}
+
+.choice-box .context-menu {
+	-fx-background-color: COLOR_BORDER, #FFF;
+    -fx-background-insets: 0, 1;
+}
+
 /****************************************************************************
  *																			*
  * ProgressIndicator														*

+ 6 - 0
main/ui/src/main/resources/fxml/settings.fxml

@@ -15,6 +15,7 @@
 <?import javafx.scene.control.CheckBox?>
 <?import javafx.scene.control.TextField?>
 <?import javafx.scene.layout.VBox?>
+<?import javafx.scene.control.ChoiceBox?>
 
 <VBox prefWidth="400.0" alignment="TOP_CENTER" spacing="12.0" xmlns:fx="http://javafx.com/fxml" cacheShape="true" cache="true">
 	<Label VBox.vgrow="NEVER" fx:id="versionLabel" alignment="CENTER" cacheShape="true" cache="true" />
@@ -40,6 +41,11 @@
 			<!-- Row 2 -->
 			<Label GridPane.rowIndex="2" GridPane.columnIndex="0" fx:id="useIpv6Label" text="%settings.useipv6.label" cacheShape="true" cache="true" />
 			<CheckBox GridPane.rowIndex="2" GridPane.columnIndex="1" fx:id="useIpv6Checkbox" cacheShape="true" cache="true" />
+			
+			<!-- Row 3 -->
+			<Label GridPane.rowIndex="3" GridPane.columnIndex="0" fx:id="prefGvfsSchemeLabel" text="%settings.prefGvfsScheme.label" cacheShape="true" cache="true" />
+			<ChoiceBox GridPane.rowIndex="3" GridPane.columnIndex="1" fx:id="prefGvfsScheme" GridPane.hgrow="ALWAYS" maxWidth="Infinity" cacheShape="true" cache="true" />
+			
 		</children>
 	</GridPane>
 	<Label VBox.vgrow="NEVER" text="%settings.requiresRestartLabel" alignment="CENTER" cacheShape="true" cache="true" />

+ 1 - 0
main/ui/src/main/resources/localization/en.txt

@@ -94,6 +94,7 @@ settings.checkForUpdates.label=Check for updates
 settings.port.label=WebDAV Port *
 settings.port.prompt=0 = Choose automatically
 settings.useipv6.label=Use IPv6 literal
+settings.prefGvfsScheme.label=WebDAV scheme
 settings.requiresRestartLabel=* Cryptomator needs to restart
 
 # tray icon