feat(android): implement private Rust storage runtime (#90)
Dependency security audit / rustsec (push) Failing after 23s
Dependency security audit / rustsec (push) Failing after 23s
This commit is contained in:
1 parent
180851087b
commit
874c8139a4
36 files changed
+2848
-39
No files matched your search
@@ -31,7 +31,7 @@ kotlin {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("${libs.jna.get().module}:${libs.versions.jna.get()}@aar")
|
||||
implementation(variantOf(libs.jna) { artifactType("aar") })
|
||||
implementation(libs.annotation)
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.android.test.runner)
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
package de.rfc1437.ironstorage.bridge
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import de.rfc1437.ironstorage.bridge.generated.MobileOnboardingFfiException
|
||||
import de.rfc1437.ironstorage.bridge.generated.MobilePrivateDirectories
|
||||
import de.rfc1437.ironstorage.bridge.generated.MobilePrivateStorageFfiException
|
||||
import de.rfc1437.ironstorage.bridge.generated.MobileShellState
|
||||
import de.rfc1437.ironstorage.bridge.generated.MobileTab
|
||||
import de.rfc1437.ironstorage.bridge.generated.mobileLocalOnboardingOperation
|
||||
import de.rfc1437.ironstorage.bridge.generated.setSelectedMobileTab
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class PrivateStorageTest {
|
||||
@Test
|
||||
fun canonicalSandboxInitializationAndRecreationKeepDurableLayout() {
|
||||
val context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
val directories = MobilePrivateDirectories(
|
||||
context.filesDir.canonicalPath,
|
||||
context.noBackupFilesDir.canonicalPath,
|
||||
context.cacheDir.canonicalPath
|
||||
)
|
||||
val native = NativeRuntime(context)
|
||||
val initialized = try {
|
||||
native.privateStorage(directories)
|
||||
} catch (error: MobilePrivateStorageFfiException.Failed) {
|
||||
throw AssertionError("Private initialization failed: ${error.kind}", error)
|
||||
}
|
||||
initialized.use { first ->
|
||||
assertEquals(1u, first.status().version)
|
||||
assertEquals(null, first.status().recovery)
|
||||
val configured = first.status().configured
|
||||
assertEquals(
|
||||
if (configured) MobileShellState.READY else MobileShellState.EMPTY,
|
||||
first.shell().pages.first().state
|
||||
)
|
||||
val layout = first.layout()
|
||||
assertEquals("${context.noBackupFilesDir.canonicalPath}/ironstorage", layout.data)
|
||||
assertEquals("${layout.data}/totp-catalog.toml", layout.catalog)
|
||||
assertEquals("${context.cacheDir.canonicalPath}/ironstorage", layout.cache)
|
||||
first.activate()
|
||||
if (!configured) {
|
||||
mobileLocalOnboardingOperation().use { onboarding ->
|
||||
try {
|
||||
onboarding.generate(
|
||||
"Sandbox fixture <fixture@example.test>",
|
||||
"public-test-passphrase",
|
||||
false
|
||||
)
|
||||
} catch (error: MobileOnboardingFfiException.Failed) {
|
||||
throw AssertionError("Private onboarding failed: ${error.kind}", error)
|
||||
}
|
||||
}
|
||||
}
|
||||
assertTrue(first.status().configured)
|
||||
setSelectedMobileTab(MobileTab.PREFERENCES)
|
||||
assertEquals(MobileTab.PREFERENCES, first.shell().selectedTab)
|
||||
assertEquals(MobileShellState.READY, first.shell().pages.first().state)
|
||||
first.clearDisposableCache()
|
||||
native.privateStorage(directories).use { recreated ->
|
||||
assertEquals(layout, recreated.layout())
|
||||
assertEquals(first.status(), recreated.status())
|
||||
}
|
||||
assertFalse(layout.toString().contains(context.noBackupFilesDir.path))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,13 @@ package de.rfc1437.ironstorage.bridge
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.Looper
|
||||
import de.rfc1437.ironstorage.bridge.generated.MobilePrivateDirectories
|
||||
import de.rfc1437.ironstorage.bridge.generated.MobilePrivateRuntime
|
||||
import de.rfc1437.ironstorage.bridge.generated.MobilePrivateStorageFfiException
|
||||
import de.rfc1437.ironstorage.bridge.generated.MobileShell
|
||||
import de.rfc1437.ironstorage.bridge.generated.MobileShellState
|
||||
import de.rfc1437.ironstorage.bridge.generated.mobileShellFixture
|
||||
import de.rfc1437.ironstorage.bridge.generated.openMobilePrivateRuntime
|
||||
import de.rfc1437.ironstorage.bridge.generated.uniffiEnsureInitialized
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
@@ -24,6 +28,11 @@ class NativeRuntime(context: Context) {
|
||||
mobileShellFixture(state)
|
||||
}
|
||||
|
||||
fun privateStorage(directories: MobilePrivateDirectories): MobilePrivateRuntime = call {
|
||||
initialize()
|
||||
openMobilePrivateRuntime(directories)
|
||||
}
|
||||
|
||||
private fun initialize() = synchronized(lock) {
|
||||
initializationFailure?.let { throw NativeBridgeException(it) }
|
||||
if (!initialized) {
|
||||
@@ -51,6 +60,8 @@ class NativeRuntime(context: Context) {
|
||||
fail(error.kind)
|
||||
} catch (error: CancellationException) {
|
||||
throw error
|
||||
} catch (error: MobilePrivateStorageFfiException) {
|
||||
throw error
|
||||
} catch (error: NativeBindingMismatchException) {
|
||||
fail(error.kind)
|
||||
} catch (_: IOException) {
|
||||
|
||||
Reference in new issue
Block a user