From ce12af84955073597fe8639c6f19df9820c22e06 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Fri, 2 Sep 2016 15:49:09 +0200 Subject: [PATCH] Added save password functionality to UI --- .../cryptomator/keychain/KeychainAccess.java | 2 +- .../keychain/MacSystemKeychainAccess.java | 6 +- .../keychain/WindowsSystemKeychainAccess.java | 2 +- .../keychain/KeychainComponent.java | 2 +- .../keychain/MapKeychainAccess.java | 10 ++- main/pom.xml | 8 +- main/ui/pom.xml | 4 + .../org/cryptomator/ui/CryptomatorModule.java | 3 +- .../controllers/ChangePasswordController.java | 19 ++-- .../ui/controllers/InitializeController.java | 17 ++-- .../ui/controllers/MainController.java | 13 ++- .../ui/controllers/UnlockController.java | 89 +++++++++++-------- .../ui/controllers/UpgradeController.java | 22 +++-- main/ui/src/main/resources/fxml/unlock.fxml | 12 ++- .../ui/src/main/resources/localization/en.txt | 1 + 15 files changed, 121 insertions(+), 89 deletions(-) rename main/keychain/src/{main => test}/java/org/cryptomator/keychain/KeychainComponent.java (85%) diff --git a/main/keychain/src/main/java/org/cryptomator/keychain/KeychainAccess.java b/main/keychain/src/main/java/org/cryptomator/keychain/KeychainAccess.java index 35e406752..abd7a3ee8 100644 --- a/main/keychain/src/main/java/org/cryptomator/keychain/KeychainAccess.java +++ b/main/keychain/src/main/java/org/cryptomator/keychain/KeychainAccess.java @@ -14,7 +14,7 @@ public interface KeychainAccess { * @param key Unique key previously used while {@link #storePassphrase(String, CharSequence) storing a passphrase}. * @return The stored passphrase for the given key or null if no value for the given key could be found. */ - CharSequence loadPassphrase(String key); + char[] loadPassphrase(String key); /** * Deletes a passphrase with a given key. diff --git a/main/keychain/src/main/java/org/cryptomator/keychain/MacSystemKeychainAccess.java b/main/keychain/src/main/java/org/cryptomator/keychain/MacSystemKeychainAccess.java index c8ab83c8c..a80d084ef 100644 --- a/main/keychain/src/main/java/org/cryptomator/keychain/MacSystemKeychainAccess.java +++ b/main/keychain/src/main/java/org/cryptomator/keychain/MacSystemKeychainAccess.java @@ -1,7 +1,5 @@ package org.cryptomator.keychain; -import java.nio.CharBuffer; - import javax.inject.Inject; import javax.inject.Singleton; @@ -29,8 +27,8 @@ class MacSystemKeychainAccess implements KeychainAccessStrategy { } @Override - public CharSequence loadPassphrase(String key) { - return CharBuffer.wrap(keychain.loadPassword(key)); + public char[] loadPassphrase(String key) { + return keychain.loadPassword(key); } @Override diff --git a/main/keychain/src/main/java/org/cryptomator/keychain/WindowsSystemKeychainAccess.java b/main/keychain/src/main/java/org/cryptomator/keychain/WindowsSystemKeychainAccess.java index cf8163141..47d56953c 100644 --- a/main/keychain/src/main/java/org/cryptomator/keychain/WindowsSystemKeychainAccess.java +++ b/main/keychain/src/main/java/org/cryptomator/keychain/WindowsSystemKeychainAccess.java @@ -32,7 +32,7 @@ class WindowsSystemKeychainAccess implements KeychainAccessStrategy { } @Override - public CharSequence loadPassphrase(String key) { + public char[] loadPassphrase(String key) { // TODO Auto-generated method stub return null; } diff --git a/main/keychain/src/main/java/org/cryptomator/keychain/KeychainComponent.java b/main/keychain/src/test/java/org/cryptomator/keychain/KeychainComponent.java similarity index 85% rename from main/keychain/src/main/java/org/cryptomator/keychain/KeychainComponent.java rename to main/keychain/src/test/java/org/cryptomator/keychain/KeychainComponent.java index 0264aa3fc..44301ed7f 100644 --- a/main/keychain/src/main/java/org/cryptomator/keychain/KeychainComponent.java +++ b/main/keychain/src/test/java/org/cryptomator/keychain/KeychainComponent.java @@ -8,7 +8,7 @@ import dagger.Component; @Singleton @Component(modules = KeychainModule.class) -public interface KeychainComponent { +interface KeychainComponent { Optional keychainAccess(); diff --git a/main/keychain/src/test/java/org/cryptomator/keychain/MapKeychainAccess.java b/main/keychain/src/test/java/org/cryptomator/keychain/MapKeychainAccess.java index dd06319cd..081a0b0e6 100644 --- a/main/keychain/src/test/java/org/cryptomator/keychain/MapKeychainAccess.java +++ b/main/keychain/src/test/java/org/cryptomator/keychain/MapKeychainAccess.java @@ -5,15 +5,19 @@ import java.util.Map; class MapKeychainAccess implements KeychainAccessStrategy { - private final Map map = new HashMap<>(); + private final Map map = new HashMap<>(); @Override public void storePassphrase(String key, CharSequence passphrase) { - map.put(key, passphrase); + char[] pw = new char[passphrase.length()]; + for (int i = 0; i < passphrase.length(); i++) { + pw[i] = passphrase.charAt(i); + } + map.put(key, pw); } @Override - public CharSequence loadPassphrase(String key) { + public char[] loadPassphrase(String key) { return map.get(key); } diff --git a/main/pom.xml b/main/pom.xml index bb9d47a8b..1a412a88a 100644 --- a/main/pom.xml +++ b/main/pom.xml @@ -58,7 +58,6 @@ ${project.version} test - org.cryptomator filesystem-api @@ -107,7 +106,6 @@ filesystem-stats ${project.version} - org.cryptomator frontend-api @@ -118,7 +116,11 @@ frontend-webdav ${project.version} - + + org.cryptomator + keychain + ${project.version} + org.cryptomator ui diff --git a/main/ui/pom.xml b/main/ui/pom.xml index bf6ab3fec..a0e7a0749 100644 --- a/main/ui/pom.xml +++ b/main/ui/pom.xml @@ -58,6 +58,10 @@ org.cryptomator jni + + org.cryptomator + keychain + diff --git a/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java b/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java index 473e213d0..3de672b47 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/CryptomatorModule.java @@ -25,6 +25,7 @@ import org.cryptomator.frontend.webdav.WebDavModule; import org.cryptomator.frontend.webdav.WebDavServer; import org.cryptomator.jni.JniModule; import org.cryptomator.jni.MacFunctions; +import org.cryptomator.keychain.KeychainModule; import org.cryptomator.ui.model.Vault; import org.cryptomator.ui.model.VaultObjectMapperProvider; import org.cryptomator.ui.model.Vaults; @@ -42,7 +43,7 @@ import javafx.application.Application; import javafx.beans.Observable; import javafx.stage.Stage; -@Module(includes = {CryptoEngineModule.class, CommonsModule.class, WebDavModule.class}) +@Module(includes = {CryptoEngineModule.class, CommonsModule.class, WebDavModule.class, KeychainModule.class}) class CryptomatorModule { private static final Logger LOG = LoggerFactory.getLogger(CryptomatorModule.class); diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/ChangePasswordController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/ChangePasswordController.java index b1a76529b..c78ac51f0 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/ChangePasswordController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/ChangePasswordController.java @@ -12,6 +12,7 @@ package org.cryptomator.ui.controllers; import java.io.IOException; import java.io.UncheckedIOException; import java.net.URL; +import java.util.Objects; import java.util.Optional; import javax.inject.Inject; @@ -31,9 +32,7 @@ import javafx.application.Application; import javafx.application.Platform; import javafx.beans.binding.BooleanBinding; import javafx.beans.property.IntegerProperty; -import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleIntegerProperty; -import javafx.beans.property.SimpleObjectProperty; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Button; @@ -49,9 +48,9 @@ public class ChangePasswordController extends LocalizedFXMLViewController { private final Application app; private final PasswordStrengthUtil strengthRater; - final ObjectProperty vault = new SimpleObjectProperty<>(); - private Optional listener = Optional.empty(); private final IntegerProperty passwordStrength = new SimpleIntegerProperty(); // 0-4 + private Optional listener = Optional.empty(); + private Vault vault; @Inject public ChangePasswordController(Application app, PasswordStrengthUtil strengthRater, Localization localization) { @@ -101,7 +100,6 @@ public class ChangePasswordController extends LocalizedFXMLViewController { BooleanBinding oldPasswordIsEmpty = oldPasswordField.textProperty().isEmpty(); BooleanBinding newPasswordIsEmpty = newPasswordField.textProperty().isEmpty(); BooleanBinding passwordsDiffer = newPasswordField.textProperty().isNotEqualTo(retypePasswordField.textProperty()); - EasyBind.subscribe(vault, this::vaultDidChange); changePasswordButton.disableProperty().bind(oldPasswordIsEmpty.or(newPasswordIsEmpty.or(passwordsDiffer))); passwordStrength.bind(EasyBind.map(newPasswordField.textProperty(), strengthRater::computeRate)); @@ -118,10 +116,11 @@ public class ChangePasswordController extends LocalizedFXMLViewController { return getClass().getResource("/fxml/change_password.fxml"); } - private void vaultDidChange(Vault newVault) { - oldPasswordField.clear(); - newPasswordField.clear(); - retypePasswordField.clear(); + void setVault(Vault vault) { + this.vault = Objects.requireNonNull(vault); + oldPasswordField.swipe(); + newPasswordField.swipe(); + retypePasswordField.swipe(); // trigger "default" change to refresh key bindings: changePasswordButton.setDefaultButton(false); changePasswordButton.setDefaultButton(true); @@ -144,7 +143,7 @@ public class ChangePasswordController extends LocalizedFXMLViewController { private void didClickChangePasswordButton(ActionEvent event) { downloadsPageLink.setVisible(false); try { - vault.get().changePassphrase(oldPasswordField.getCharacters(), newPasswordField.getCharacters()); + vault.changePassphrase(oldPasswordField.getCharacters(), newPasswordField.getCharacters()); messageText.setText(localization.getString("changePassword.infoMessage.success")); listener.ifPresent(this::invokeListenerLater); } catch (InvalidPassphraseException e) { diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/InitializeController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/InitializeController.java index 2989e9eaf..9a61f28c9 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/InitializeController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/InitializeController.java @@ -13,6 +13,7 @@ import java.io.IOException; import java.io.UncheckedIOException; import java.net.URL; import java.nio.file.FileAlreadyExistsException; +import java.util.Objects; import java.util.Optional; import javax.inject.Inject; @@ -29,9 +30,7 @@ import org.slf4j.LoggerFactory; import javafx.application.Platform; import javafx.beans.binding.BooleanBinding; import javafx.beans.property.IntegerProperty; -import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleIntegerProperty; -import javafx.beans.property.SimpleObjectProperty; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Button; @@ -44,9 +43,9 @@ public class InitializeController extends LocalizedFXMLViewController { private static final Logger LOG = LoggerFactory.getLogger(InitializeController.class); private final PasswordStrengthUtil strengthRater; - final ObjectProperty vault = new SimpleObjectProperty<>(); - private Optional listener = Optional.empty(); private final IntegerProperty passwordStrength = new SimpleIntegerProperty(); // 0-4 + private Optional listener = Optional.empty(); + private Vault vault; @Inject public InitializeController(Localization localization, PasswordStrengthUtil strengthRater) { @@ -88,7 +87,6 @@ public class InitializeController extends LocalizedFXMLViewController { public void initialize() { BooleanBinding passwordIsEmpty = passwordField.textProperty().isEmpty(); BooleanBinding passwordsDiffer = passwordField.textProperty().isNotEqualTo(retypePasswordField.textProperty()); - EasyBind.subscribe(vault, this::vaultDidChange); okButton.disableProperty().bind(passwordIsEmpty.or(passwordsDiffer)); passwordStrength.bind(EasyBind.map(passwordField.textProperty(), strengthRater::computeRate)); @@ -105,9 +103,10 @@ public class InitializeController extends LocalizedFXMLViewController { return getClass().getResource("/fxml/initialize.fxml"); } - private void vaultDidChange(Vault newVault) { - passwordField.clear(); - retypePasswordField.clear(); + void setVault(Vault vault) { + this.vault = Objects.requireNonNull(vault); + passwordField.swipe(); + retypePasswordField.swipe(); // trigger "default" change to refresh key bindings: okButton.setDefaultButton(false); okButton.setDefaultButton(true); @@ -121,7 +120,7 @@ public class InitializeController extends LocalizedFXMLViewController { protected void initializeVault(ActionEvent event) { final CharSequence passphrase = passwordField.getCharacters(); try { - vault.get().create(passphrase); + vault.create(passphrase); listener.ifPresent(this::invokeListenerLater); } catch (FileAlreadyExistsException ex) { messageLabel.setText(localization.getString("initialize.messageLabel.alreadyInitialized")); diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java index 478c6be6b..9c9c194ba 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java @@ -315,7 +315,8 @@ public class MainController extends LocalizedFXMLViewController { private void showInitializeView() { final InitializeController ctrl = initializeController.get(); - ctrl.vault.bind(selectedVault); + ctrl.loadFxml(); + ctrl.setVault(selectedVault.get()); ctrl.setListener(this::didInitialize); activeController.set(ctrl); } @@ -326,7 +327,8 @@ public class MainController extends LocalizedFXMLViewController { private void showUpgradeView() { final UpgradeController ctrl = upgradeController.get(); - ctrl.vault.bind(selectedVault); + ctrl.loadFxml(); + ctrl.setVault(selectedVault.get()); ctrl.setListener(this::didUpgrade); activeController.set(ctrl); } @@ -337,7 +339,8 @@ public class MainController extends LocalizedFXMLViewController { private void showUnlockView() { final UnlockController ctrl = unlockController.get(); - ctrl.vault.bind(selectedVault); + ctrl.loadFxml(); + ctrl.setVault(selectedVault.get()); ctrl.setListener(this::didUnlock); activeController.set(ctrl); } @@ -353,6 +356,7 @@ public class MainController extends LocalizedFXMLViewController { final UnlockedController ctrl = unlockedVaults.computeIfAbsent(vault, k -> { return unlockedControllerProvider.get(); }); + ctrl.loadFxml(); ctrl.setVault(vault); ctrl.setListener(this::didLock); activeController.set(ctrl); @@ -368,7 +372,8 @@ public class MainController extends LocalizedFXMLViewController { private void showChangePasswordView() { final ChangePasswordController ctrl = changePasswordController.get(); - ctrl.vault.bind(selectedVault); + ctrl.loadFxml(); + ctrl.setVault(selectedVault.get()); ctrl.setListener(this::didChangePassword); activeController.set(ctrl); } diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java index d17175dc7..e5fe09fe4 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java @@ -9,7 +9,9 @@ package org.cryptomator.ui.controllers; import java.net.URL; +import java.util.Arrays; import java.util.Comparator; +import java.util.Objects; import java.util.Optional; import javax.inject.Inject; @@ -22,25 +24,24 @@ import org.cryptomator.frontend.CommandFailedException; import org.cryptomator.frontend.FrontendCreationFailedException; import org.cryptomator.frontend.FrontendFactory; import org.cryptomator.frontend.webdav.mount.WindowsDriveLetters; +import org.cryptomator.keychain.KeychainAccess; import org.cryptomator.ui.controls.SecPasswordField; import org.cryptomator.ui.model.Vault; import org.cryptomator.ui.settings.Localization; import org.cryptomator.ui.settings.Settings; import org.cryptomator.ui.util.AsyncTaskService; -import org.fxmisc.easybind.EasyBind; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import dagger.Lazy; import javafx.application.Application; import javafx.application.Platform; -import javafx.beans.property.ObjectProperty; -import javafx.beans.property.SimpleObjectProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Button; +import javafx.scene.control.CheckBox; import javafx.scene.control.ChoiceBox; import javafx.scene.control.Hyperlink; import javafx.scene.control.Label; @@ -61,22 +62,34 @@ public class UnlockController extends LocalizedFXMLViewController { private final Settings settings; private final WindowsDriveLetters driveLetters; private final ChangeListener driveLetterChangeListener = this::winDriveLetterDidChange; - final ObjectProperty vault = new SimpleObjectProperty<>(); + private final Optional keychainAccess; + private Vault vault; private Optional listener = Optional.empty(); @Inject - public UnlockController(Application app, Localization localization, AsyncTaskService asyncTaskService, Lazy frontendFactory, Settings settings, WindowsDriveLetters driveLetters) { + public UnlockController(Application app, Localization localization, AsyncTaskService asyncTaskService, Lazy frontendFactory, Settings settings, WindowsDriveLetters driveLetters, + Optional keychainAccess) { super(localization); this.app = app; this.asyncTaskService = asyncTaskService; this.frontendFactory = frontendFactory; this.settings = settings; this.driveLetters = driveLetters; + this.keychainAccess = keychainAccess; } @FXML private SecPasswordField passwordField; + @FXML + private Button advancedOptionsButton; + + @FXML + private Button unlockButton; + + @FXML + private CheckBox savePassword; + @FXML private TextField mountName; @@ -86,12 +99,6 @@ public class UnlockController extends LocalizedFXMLViewController { @FXML private ChoiceBox winDriveLetter; - @FXML - private Button advancedOptionsButton; - - @FXML - private Button unlockButton; - @FXML private ProgressIndicator progressIndicator; @@ -107,8 +114,10 @@ public class UnlockController extends LocalizedFXMLViewController { @Override public void initialize() { advancedOptions.managedProperty().bind(advancedOptions.visibleProperty()); + unlockButton.disableProperty().bind(passwordField.textProperty().isEmpty()); mountName.addEventFilter(KeyEvent.KEY_TYPED, this::filterAlphanumericKeyEvents); mountName.textProperty().addListener(this::mountNameDidChange); + savePassword.setDisable(!keychainAccess.isPresent()); if (SystemUtils.IS_OS_WINDOWS) { winDriveLetter.setConverter(new WinDriveLetterLabelConverter()); } else { @@ -117,9 +126,6 @@ public class UnlockController extends LocalizedFXMLViewController { winDriveLetter.setVisible(false); winDriveLetter.setManaged(false); } - unlockButton.disableProperty().bind(passwordField.textProperty().isEmpty()); - - EasyBind.subscribe(vault, this::vaultDidChange); } @Override @@ -127,11 +133,15 @@ public class UnlockController extends LocalizedFXMLViewController { return getClass().getResource("/fxml/unlock.fxml"); } - private void vaultDidChange(Vault newVault) { - if (newVault == null) { + void setVault(Vault vault) { + // trigger "default" change to refresh key bindings: + unlockButton.setDefaultButton(false); + unlockButton.setDefaultButton(true); + if (vault.equals(this.vault)) { return; } - passwordField.clear(); + this.vault = Objects.requireNonNull(vault); + passwordField.swipe(); advancedOptions.setVisible(false); advancedOptionsButton.setText(localization.getString("unlock.button.advancedOptions.show")); progressIndicator.setVisible(false); @@ -145,13 +155,21 @@ public class UnlockController extends LocalizedFXMLViewController { } downloadsPageLink.setVisible(false); messageText.setText(null); - mountName.setText(newVault.getMountName()); + mountName.setText(vault.getMountName()); if (SystemUtils.IS_OS_WINDOWS) { chooseSelectedDriveLetter(); } - // trigger "default" change to refresh key bindings: - unlockButton.setDefaultButton(false); - unlockButton.setDefaultButton(true); + savePassword.setSelected(false); + // auto-fill pw from keychain: + if (keychainAccess.isPresent()) { + char[] storedPw = keychainAccess.get().loadPassphrase(vault.getId()); + if (storedPw != null) { + savePassword.setSelected(true); + passwordField.setText(new String(storedPw)); + passwordField.selectRange(storedPw.length, storedPw.length); + Arrays.fill(storedPw, ' '); + } + } } // **************************************** @@ -188,14 +206,11 @@ public class UnlockController extends LocalizedFXMLViewController { } private void mountNameDidChange(ObservableValue property, String oldValue, String newValue) { - if (vault.get() == null) { - return; - } // newValue is guaranteed to be a-z0-9_, see #filterAlphanumericKeyEvents if (newValue.isEmpty()) { - mountName.setText(vault.get().getMountName()); + mountName.setText(vault.getMountName()); } else { - vault.get().setMountName(newValue); + vault.setMountName(newValue); } } @@ -242,20 +257,17 @@ public class UnlockController extends LocalizedFXMLViewController { } private void winDriveLetterDidChange(ObservableValue property, Character oldValue, Character newValue) { - if (vault.get() == null) { - return; - } - vault.get().setWinDriveLetter(newValue); + vault.setWinDriveLetter(newValue); settings.save(); } private void chooseSelectedDriveLetter() { assert SystemUtils.IS_OS_WINDOWS; // if the vault prefers a drive letter, that is currently occupied, this is our last chance to reset this: - if (driveLetters.getOccupiedDriveLetters().contains(vault.get().getWinDriveLetter())) { - vault.get().setWinDriveLetter(null); + if (driveLetters.getOccupiedDriveLetters().contains(vault.getWinDriveLetter())) { + vault.setWinDriveLetter(null); } - final Character letter = vault.get().getWinDriveLetter(); + final Character letter = vault.getWinDriveLetter(); if (letter == null) { // first option is known to be 'auto-assign' due to #WinDriveLetterComparator. this.winDriveLetter.getSelectionModel().selectFirst(); @@ -275,10 +287,10 @@ public class UnlockController extends LocalizedFXMLViewController { progressIndicator.setVisible(true); downloadsPageLink.setVisible(false); CharSequence password = passwordField.getCharacters(); - asyncTaskService.asyncTaskOf(() -> this.unlock(vault.get(), password)).run(); + asyncTaskService.asyncTaskOf(() -> this.unlock(password)).run(); } - private void unlock(Vault vault, CharSequence password) { + private void unlock(CharSequence password) { try { vault.activateFrontend(frontendFactory.get(), settings, password); vault.reveal(); @@ -286,9 +298,15 @@ public class UnlockController extends LocalizedFXMLViewController { messageText.setText(null); listener.ifPresent(lstnr -> lstnr.didUnlock(vault)); }); + if (keychainAccess.isPresent() && savePassword.isSelected()) { + keychainAccess.get().storePassphrase(vault.getId(), password); + } else { + passwordField.swipe(); + } } catch (InvalidPassphraseException e) { Platform.runLater(() -> { messageText.setText(localization.getString("unlock.errorMessage.wrongPassword")); + passwordField.selectAll(); passwordField.requestFocus(); }); } catch (UnsupportedVaultFormatException e) { @@ -307,7 +325,6 @@ public class UnlockController extends LocalizedFXMLViewController { }); } finally { Platform.runLater(() -> { - passwordField.swipe(); mountName.setDisable(false); advancedOptionsButton.setDisable(false); progressIndicator.setVisible(false); diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/UpgradeController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/UpgradeController.java index a34e2aeb6..8e6a4e97f 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/UpgradeController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/UpgradeController.java @@ -27,11 +27,11 @@ import javafx.scene.control.ProgressIndicator; public class UpgradeController extends LocalizedFXMLViewController { - final ObjectProperty vault = new SimpleObjectProperty<>(); - final ObjectProperty> strategy = new SimpleObjectProperty<>(); + private final ObjectProperty> strategy = new SimpleObjectProperty<>(); private final UpgradeStrategies strategies; private final AsyncTaskService asyncTaskService; private Optional listener = Optional.empty(); + private Vault vault; @Inject public UpgradeController(Localization localization, UpgradeStrategies strategies, AsyncTaskService asyncTaskService) { @@ -67,8 +67,6 @@ public class UpgradeController extends LocalizedFXMLViewController { BooleanExpression passwordProvided = passwordField.textProperty().isNotEmpty().and(passwordField.disabledProperty().not()); BooleanExpression syncFinished = confirmationCheckbox.selectedProperty(); upgradeButton.disableProperty().bind(passwordProvided.not().or(syncFinished.not())); - - EasyBind.subscribe(vault, this::vaultDidChange); } @Override @@ -76,9 +74,10 @@ public class UpgradeController extends LocalizedFXMLViewController { return getClass().getResource("/fxml/upgrade.fxml"); } - private void vaultDidChange(Vault newVault) { + void setVault(Vault vault) { + this.vault = Objects.requireNonNull(vault); errorLabel.setText(null); - strategy.set(strategies.getUpgradeStrategy(newVault)); + strategy.set(strategies.getUpgradeStrategy(vault)); // trigger "default" change to refresh key bindings: upgradeButton.setDefaultButton(false); upgradeButton.setDefaultButton(true); @@ -89,7 +88,7 @@ public class UpgradeController extends LocalizedFXMLViewController { // **************************************** private String upgradeNotification(UpgradeStrategy instruction) { - return instruction.getNotification(vault.get()); + return instruction.getNotification(vault); } // **************************************** @@ -102,15 +101,14 @@ public class UpgradeController extends LocalizedFXMLViewController { } private void upgrade(UpgradeStrategy instruction) { - Vault v = Objects.requireNonNull(vault.getValue()); passwordField.setDisable(true); progressIndicator.setVisible(true); asyncTaskService // .asyncTaskOf(() -> { - if (!instruction.isApplicable(v)) { - throw new IllegalStateException("No ugprade needed for " + v.path().getValue()); + if (!instruction.isApplicable(vault)) { + throw new IllegalStateException("No ugprade needed for " + vault.path().getValue()); } - instruction.upgrade(v, passwordField.getCharacters()); + instruction.upgrade(vault, passwordField.getCharacters()); }) // .onSuccess(this::showNextUpgrade) // .onError(UpgradeFailedException.class, e -> { @@ -125,7 +123,7 @@ public class UpgradeController extends LocalizedFXMLViewController { private void showNextUpgrade() { errorLabel.setText(null); - Optional nextStrategy = strategies.getUpgradeStrategy(vault.getValue()); + Optional nextStrategy = strategies.getUpgradeStrategy(vault); if (nextStrategy.isPresent()) { strategy.set(nextStrategy); } else { diff --git a/main/ui/src/main/resources/fxml/unlock.fxml b/main/ui/src/main/resources/fxml/unlock.fxml index 851d33fc9..0a8ea2fb8 100644 --- a/main/ui/src/main/resources/fxml/unlock.fxml +++ b/main/ui/src/main/resources/fxml/unlock.fxml @@ -68,12 +68,16 @@ -