diff --git a/main/pom.xml b/main/pom.xml index 60ef7e7e9..293302bd2 100644 --- a/main/pom.xml +++ b/main/pom.xml @@ -25,7 +25,7 @@ 16 - 2.1.0-beta2 + 2.1.0-beta3 1.0.0-beta2 1.0.0-beta2 1.0.0-beta2 diff --git a/main/ui/src/main/java/org/cryptomator/ui/health/CheckController.java b/main/ui/src/main/java/org/cryptomator/ui/health/CheckController.java index 28b7a4915..86400780a 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/health/CheckController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/health/CheckController.java @@ -10,11 +10,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; import javafx.fxml.FXML; +import javafx.scene.control.ListView; import javafx.stage.Stage; import java.security.SecureRandom; -import java.util.ArrayList; -import java.util.List; import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.atomic.AtomicReference; @@ -22,40 +25,61 @@ import java.util.concurrent.atomic.AtomicReference; @HealthCheckScoped public class CheckController implements FxController { - private static final Logger LOG = LoggerFactory.getLogger(CheckController.class); - - private final Vault vault; private final Stage window; - private final Masterkey masterkey; private final VaultConfig vaultConfig; - private final SecureRandom csprng; + private final HealthCheckTaskFactory healthCheckTaskFactory; private final ExecutorService executor; + private final ObjectProperty selectedCheck; + private final ObservableList checks; + private final ObservableList results; + + public ListView checksListView; + public ListView resultsListView; @Inject - public CheckController(@HealthCheckWindow Vault vault, @HealthCheckWindow Stage window, AtomicReference masterkeyRef, AtomicReference vaultConfigRef, SecureRandom csprng, ExecutorService executor) { - this.vault = vault; + public CheckController(@HealthCheckWindow Stage window, AtomicReference vaultConfigRef, HealthCheckTaskFactory healthCheckTaskFactory, ExecutorService executor, ObjectProperty selectedCheck) { this.window = window; - this.masterkey = Objects.requireNonNull(masterkeyRef.get()); this.vaultConfig = Objects.requireNonNull(vaultConfigRef.get()); - this.csprng = csprng; + this.healthCheckTaskFactory = healthCheckTaskFactory; this.executor = executor; + this.selectedCheck = selectedCheck; + this.checks = FXCollections.observableArrayList(HealthCheck.allChecks()); + this.results = FXCollections.observableArrayList(); + } + + @FXML + public void initialize() { + checksListView.setItems(checks); + checksListView.setCellFactory(this::createCheckListCell); + resultsListView.setItems(results); + resultsListView.setCellFactory(this::createResultListCell); + selectedCheck.bind(checksListView.getSelectionModel().selectedItemProperty()); + } + + private CheckListCell createCheckListCell(ListView list) { + return new CheckListCell(); + } + + private ResultListCell createResultListCell(ListView list) { + return new ResultListCell(); } @FXML public void runCheck() { - try (var cryptor = vaultConfig.getCipherCombo().getCryptorProvider(csprng).withKey(masterkey)) { - HealthCheck.allChecks().stream() - .peek(check -> { - LOG.info("Running check: {}", check.identifier()); - }) - .flatMap(check -> check.check(vault.getPath(), vaultConfig, masterkey, cryptor, executor)) - .forEach(result -> { - LOG.info("Result: {}", result); - }); - } + executor.execute(healthCheckTaskFactory.newTask(selectedCheck.get(), results::add)); } + /* Getter/Setter */ + public VaultConfig getVaultConfig() { return vaultConfig; } + + public HealthCheck getSelectedCheck() { + return selectedCheck.get(); + } + + public ReadOnlyObjectProperty selectedCheckProperty() { + return selectedCheck; + } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/health/CheckListCell.java b/main/ui/src/main/java/org/cryptomator/ui/health/CheckListCell.java new file mode 100644 index 000000000..09e73b4b8 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/health/CheckListCell.java @@ -0,0 +1,16 @@ +package org.cryptomator.ui.health; + +import org.cryptomator.cryptofs.health.api.HealthCheck; + +import javafx.scene.control.ListCell; + +class CheckListCell extends ListCell { + + @Override + protected void updateItem(HealthCheck item, boolean empty) { + super.updateItem(item, empty); + if (item != null) { + setText(item.identifier()); + } + } +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/health/HealthCheckModule.java b/main/ui/src/main/java/org/cryptomator/ui/health/HealthCheckModule.java index 0a17678fc..c6b370469 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/health/HealthCheckModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/health/HealthCheckModule.java @@ -6,6 +6,7 @@ import dagger.Provides; import dagger.multibindings.IntoMap; import org.cryptomator.common.vaults.Vault; import org.cryptomator.cryptofs.VaultConfig; +import org.cryptomator.cryptofs.health.api.HealthCheck; import org.cryptomator.cryptolib.api.Masterkey; import org.cryptomator.ui.common.DefaultSceneFactory; import org.cryptomator.ui.common.FxController; @@ -19,9 +20,9 @@ import org.cryptomator.ui.keyloading.KeyLoadingStrategy; import org.cryptomator.ui.mainwindow.MainWindow; import javax.inject.Provider; -import javafx.beans.Observable; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; import javafx.scene.Scene; import javafx.stage.Modality; import javafx.stage.Stage; @@ -33,6 +34,12 @@ import java.util.concurrent.atomic.AtomicReference; @Module(subcomponents = {KeyLoadingComponent.class}) abstract class HealthCheckModule { + @Provides + @HealthCheckScoped + static ObjectProperty selectedHealthCheck() { + return new SimpleObjectProperty(); + } + @Provides @HealthCheckScoped static AtomicReference provideMasterkeyRef() { diff --git a/main/ui/src/main/java/org/cryptomator/ui/health/HealthCheckTask.java b/main/ui/src/main/java/org/cryptomator/ui/health/HealthCheckTask.java new file mode 100644 index 000000000..7243fcd3d --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/health/HealthCheckTask.java @@ -0,0 +1,60 @@ +package org.cryptomator.ui.health; + +import org.cryptomator.cryptofs.VaultConfig; +import org.cryptomator.cryptofs.health.api.DiagnosticResult; +import org.cryptomator.cryptofs.health.api.HealthCheck; +import org.cryptomator.cryptolib.api.Masterkey; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javafx.application.Platform; +import javafx.concurrent.Task; +import java.nio.file.Path; +import java.security.SecureRandom; +import java.util.Objects; +import java.util.concurrent.CancellationException; +import java.util.function.Consumer; + +class HealthCheckTask extends Task { + + private static final Logger LOG = LoggerFactory.getLogger(HealthCheckTask.class); + + private final Path vaultPath; + private final VaultConfig vaultConfig; + private final Masterkey masterkey; + private final SecureRandom csprng; + private final HealthCheck check; + private final Consumer resultConsumer; + + public HealthCheckTask(Path vaultPath, VaultConfig vaultConfig, Masterkey masterkey, SecureRandom csprng, HealthCheck check, Consumer resultConsumer) { + this.vaultPath = vaultPath; + this.vaultConfig = vaultConfig; + this.masterkey = masterkey; + this.csprng = csprng; + this.check = Objects.requireNonNull(check); + this.resultConsumer = resultConsumer; + } + + @Override + protected Void call() { + try (var cryptor = vaultConfig.getCipherCombo().getCryptorProvider(csprng).withKey(masterkey)) { + check.check(vaultPath, vaultConfig, masterkey, cryptor, result -> { + if (isCancelled()) { + throw new CancellationException(); + } + Platform.runLater(() -> resultConsumer.accept(result)); + }); + } + return null; + } + + @Override + protected void scheduled() { + LOG.info("starting {}", check.identifier()); + } + + @Override + protected void done() { + LOG.info("finished {}", check.identifier()); + } +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/health/HealthCheckTaskFactory.java b/main/ui/src/main/java/org/cryptomator/ui/health/HealthCheckTaskFactory.java new file mode 100644 index 000000000..3d192e0fe --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/health/HealthCheckTaskFactory.java @@ -0,0 +1,35 @@ +package org.cryptomator.ui.health; + +import org.cryptomator.common.vaults.Vault; +import org.cryptomator.cryptofs.VaultConfig; +import org.cryptomator.cryptofs.health.api.DiagnosticResult; +import org.cryptomator.cryptofs.health.api.HealthCheck; +import org.cryptomator.cryptolib.api.Masterkey; + +import javax.inject.Inject; +import java.security.SecureRandom; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; + +@HealthCheckScoped +class HealthCheckTaskFactory { + + private final Vault vault; + private final Masterkey masterkey; + private final VaultConfig vaultConfig; + private final SecureRandom csprng; + + @Inject + public HealthCheckTaskFactory(@HealthCheckWindow Vault vault, AtomicReference masterkeyRef, AtomicReference vaultConfigRef, SecureRandom csprng) { + this.vault = vault; + this.masterkey = Objects.requireNonNull(masterkeyRef.get()); + this.vaultConfig = Objects.requireNonNull(vaultConfigRef.get()); + this.csprng = csprng; + } + + public HealthCheckTask newTask(HealthCheck healthCheck, Consumer resultConsumer) { + return new HealthCheckTask(vault.getPath(), vaultConfig, masterkey, csprng, healthCheck, resultConsumer); + } + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/health/ResultListCell.java b/main/ui/src/main/java/org/cryptomator/ui/health/ResultListCell.java new file mode 100644 index 000000000..1b0d02a11 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/health/ResultListCell.java @@ -0,0 +1,17 @@ +package org.cryptomator.ui.health; + +import org.cryptomator.cryptofs.health.api.DiagnosticResult; +import org.cryptomator.cryptofs.health.api.HealthCheck; + +import javafx.scene.control.ListCell; + +class ResultListCell extends ListCell { + + @Override + protected void updateItem(DiagnosticResult item, boolean empty) { + super.updateItem(item, empty); + if (item != null) { + setText(item.toString()); + } + } +} diff --git a/main/ui/src/main/resources/fxml/health_check.fxml b/main/ui/src/main/resources/fxml/health_check.fxml index 42942e01b..0ed5ff104 100644 --- a/main/ui/src/main/resources/fxml/health_check.fxml +++ b/main/ui/src/main/resources/fxml/health_check.fxml @@ -5,7 +5,9 @@ - + + -