From 7d0bdc1a63695132cc06dd051a34d86605e94335 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 27 Nov 2019 15:44:53 +0100 Subject: [PATCH] Show stack trace in case of unexpected exceptions --- .../org/cryptomator/ui/common/FxmlFile.java | 1 + .../ui/common/StackTraceController.java | 28 ++++++++++++++++ .../ui/unlock/UnlockController.java | 11 +++++-- .../unlock/UnlockGenericErrorController.java | 29 +++++++++++++++++ .../cryptomator/ui/unlock/UnlockModule.java | 29 +++++++++++++++++ .../src/main/resources/fxml/stacktrace.fxml | 29 +++++++++++++++++ .../resources/fxml/unlock_generic_error.fxml | 32 +++++++++++++++++++ .../main/resources/i18n/strings.properties | 3 ++ 8 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 main/ui/src/main/java/org/cryptomator/ui/common/StackTraceController.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockGenericErrorController.java create mode 100644 main/ui/src/main/resources/fxml/stacktrace.fxml create mode 100644 main/ui/src/main/resources/fxml/unlock_generic_error.fxml diff --git a/main/ui/src/main/java/org/cryptomator/ui/common/FxmlFile.java b/main/ui/src/main/java/org/cryptomator/ui/common/FxmlFile.java index 944af9e28..c25562bdc 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/common/FxmlFile.java +++ b/main/ui/src/main/java/org/cryptomator/ui/common/FxmlFile.java @@ -21,6 +21,7 @@ public enum FxmlFile { RECOVERYKEY_SUCCESS("/fxml/recoverykey_success.fxml"), // REMOVE_VAULT("/fxml/remove_vault.fxml"), // UNLOCK("/fxml/unlock.fxml"), + UNLOCK_GENERIC_ERROR("/fxml/unlock_generic_error.fxml"), // UNLOCK_SUCCESS("/fxml/unlock_success.fxml"), // VAULT_OPTIONS("/fxml/vault_options.fxml"), // WRONGFILEALERT("/fxml/wrongfilealert.fxml"); diff --git a/main/ui/src/main/java/org/cryptomator/ui/common/StackTraceController.java b/main/ui/src/main/java/org/cryptomator/ui/common/StackTraceController.java new file mode 100644 index 000000000..accab1b89 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/common/StackTraceController.java @@ -0,0 +1,28 @@ +package org.cryptomator.ui.common; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.nio.charset.StandardCharsets; + +public class StackTraceController implements FxController { + + private final String stackTrace; + + public StackTraceController(Exception cause) { + this.stackTrace = provideStackTrace(cause); + } + + static String provideStackTrace(Exception cause) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + cause.printStackTrace(new PrintStream(baos)); + return baos.toString(StandardCharsets.UTF_8); + } + + /* Getter/Setter */ + + public String getStackTrace() { + return stackTrace; + } + + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockController.java b/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockController.java index 7c1221aaf..76b1c591a 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockController.java @@ -7,6 +7,7 @@ import javafx.animation.Timeline; import javafx.beans.binding.Bindings; import javafx.beans.binding.ObjectBinding; import javafx.beans.property.BooleanProperty; +import javafx.beans.property.ObjectProperty; import javafx.beans.property.ReadOnlyBooleanProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.value.WritableValue; @@ -32,6 +33,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; +import javax.inject.Named; import java.nio.file.DirectoryNotEmptyException; import java.nio.file.NotDirectoryException; import java.util.Arrays; @@ -49,19 +51,23 @@ public class UnlockController implements FxController { private final ObjectBinding unlockButtonState; private final Optional keychainAccess; private final Lazy successScene; + private final Lazy genericErrorScene; + private final ObjectProperty genericErrorCause; private final ForgetPasswordComponent.Builder forgetPassword; private final BooleanProperty unlockButtonDisabled; public NiceSecurePasswordField passwordField; public CheckBox savePassword; @Inject - public UnlockController(@UnlockWindow Stage window, @UnlockWindow Vault vault, ExecutorService executor, Optional keychainAccess, @FxmlScene(FxmlFile.UNLOCK_SUCCESS) Lazy successScene, ForgetPasswordComponent.Builder forgetPassword) { + public UnlockController(@UnlockWindow Stage window, @UnlockWindow Vault vault, ExecutorService executor, Optional keychainAccess, @FxmlScene(FxmlFile.UNLOCK_SUCCESS) Lazy successScene, @FxmlScene(FxmlFile.UNLOCK_GENERIC_ERROR) Lazy genericErrorScene, @Named("genericErrorCause") ObjectProperty genericErrorCause, ForgetPasswordComponent.Builder forgetPassword) { this.window = window; this.vault = vault; this.executor = executor; this.unlockButtonState = Bindings.createObjectBinding(this::getUnlockButtonState, vault.stateProperty()); this.keychainAccess = keychainAccess; this.successScene = successScene; + this.genericErrorScene = genericErrorScene; + this.genericErrorCause = genericErrorCause; this.forgetPassword = forgetPassword; this.unlockButtonDisabled = new SimpleBooleanProperty(); } @@ -110,7 +116,8 @@ public class UnlockController implements FxController { // TODO }).onError(Exception.class, e -> { // including RuntimeExceptions LOG.error("Unlock failed for technical reasons.", e); - // TODO + genericErrorCause.set(e); + window.setScene(genericErrorScene.get()); }).andFinally(() -> { if (!vault.isUnlocked()) { vault.setState(VaultState.LOCKED); diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockGenericErrorController.java b/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockGenericErrorController.java new file mode 100644 index 000000000..faa357969 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockGenericErrorController.java @@ -0,0 +1,29 @@ +package org.cryptomator.ui.unlock; + +import dagger.Lazy; +import javafx.fxml.FXML; +import javafx.scene.Scene; +import javafx.stage.Stage; +import org.cryptomator.ui.common.FxController; +import org.cryptomator.ui.common.FxmlFile; +import org.cryptomator.ui.common.FxmlScene; + +import javax.inject.Inject; + +@UnlockScoped +public class UnlockGenericErrorController implements FxController { + + private final Stage window; + private final Lazy unlockScene; + + @Inject + UnlockGenericErrorController(@UnlockWindow Stage window, @FxmlScene(FxmlFile.UNLOCK) Lazy unlockScene) { + this.window = window; + this.unlockScene = unlockScene; + } + + @FXML + public void back() { + window.setScene(unlockScene.get()); + } +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockModule.java b/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockModule.java index 488f7cfa8..6ab89f658 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockModule.java @@ -4,6 +4,8 @@ import dagger.Binds; import dagger.Module; import dagger.Provides; import dagger.multibindings.IntoMap; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; import javafx.scene.Scene; import javafx.scene.image.Image; import javafx.stage.Modality; @@ -14,6 +16,7 @@ import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxControllerKey; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; +import org.cryptomator.ui.common.StackTraceController; import org.cryptomator.ui.forgetPassword.ForgetPasswordComponent; import javax.inject.Named; @@ -44,6 +47,13 @@ abstract class UnlockModule { return stage; } + @Provides + @Named("genericErrorCause") + @UnlockScoped + static ObjectProperty provideGenericErrorCause() { + return new SimpleObjectProperty<>(); + } + @Provides @FxmlScene(FxmlFile.UNLOCK) @UnlockScoped @@ -58,6 +68,13 @@ abstract class UnlockModule { return fxmlLoaders.createScene("/fxml/unlock_success.fxml"); } + @Provides + @FxmlScene(FxmlFile.UNLOCK_GENERIC_ERROR) + @UnlockScoped + static Scene provideGenericErrorScene(@UnlockWindow FXMLLoaderFactory fxmlLoaders) { + return fxmlLoaders.createScene("/fxml/unlock_generic_error.fxml"); + } + // ------------------ @@ -71,5 +88,17 @@ abstract class UnlockModule { @FxControllerKey(UnlockSuccessController.class) abstract FxController bindUnlockSuccessController(UnlockSuccessController controller); + @Binds + @IntoMap + @FxControllerKey(UnlockGenericErrorController.class) + abstract FxController bindUnlockGenericErrorController(UnlockGenericErrorController controller); + + @Provides + @IntoMap + @FxControllerKey(StackTraceController.class) + static FxController provideStackTraceController(@Named("genericErrorCause") ObjectProperty errorCause) { + return new StackTraceController(errorCause.get()); + } + } diff --git a/main/ui/src/main/resources/fxml/stacktrace.fxml b/main/ui/src/main/resources/fxml/stacktrace.fxml new file mode 100644 index 000000000..3c150449d --- /dev/null +++ b/main/ui/src/main/resources/fxml/stacktrace.fxml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + +