Compare commits

..

12 Commits

Author SHA1 Message Date
akwizgran
a872851a78 Revert minSdkVersion to 21 to fix Robolectric tests. 2023-09-05 17:29:05 +01:00
akwizgran
f3050f9fb8 Fix packaging of Tor binaries with minSdkVersion >= 23. 2023-09-05 17:07:59 +01:00
akwizgran
a3ba1ac91e Fix Gradle Witness. 2023-09-05 16:38:36 +01:00
akwizgran
0ac4b5c613 Don't delete .gitkeep when cleaning. 2023-09-05 15:27:01 +01:00
akwizgran
f4425acfaf Keep jniLibs dir, as it's now an input of the clean task. 2023-09-05 15:23:33 +01:00
akwizgran
7b65c63bc9 Package Android binaries, enable desugaring, bump min API level.
FIXME: Desugaring ConcurrentHashMap.newKeySet() requires
desugar_jdk_libs version 2, which requires bumping the Android Gradle
plugin version. This seems to have broken Gradle Witness.
2023-09-05 14:50:23 +01:00
akwizgran
bf2de56abe Use SqliteDatabase as default implementation. 2023-09-05 10:48:58 +01:00
akwizgran
8d7ac49bff Enable secure_delete for SQLite. 2023-09-05 10:48:36 +01:00
akwizgran
9b2c8b0f98 Fix default value for sync versions. 2023-09-05 10:37:07 +01:00
akwizgran
b7c0bc468f WIP: Create indexes on foreign key columns if needed. 2023-09-04 17:42:02 +01:00
akwizgran
852f3fd78b WIP: Temporarily skip failing test so we can run performance test. 2023-09-01 11:51:05 +01:00
akwizgran
6734284585 WIP: Add SQLite DB backend using sqlite-jdbc-crypt. 2023-09-01 11:42:24 +01:00
214 changed files with 2248 additions and 5373 deletions

View File

@@ -7,7 +7,6 @@ stages:
variables: variables:
GIT_SUBMODULE_STRATEGY: recursive GIT_SUBMODULE_STRATEGY: recursive
JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64
workflow: workflow:
# when to create a CI pipeline # when to create a CI pipeline
@@ -105,3 +104,12 @@ mailbox integration test:
script: script:
- (cd briar-mailbox; git fetch; git reset --hard origin/main) - (cd briar-mailbox; git fetch; git reset --hard origin/main)
- MAILBOX_INTEGRATION_TESTS=true ./gradlew --info mailbox-integration-tests:test - MAILBOX_INTEGRATION_TESTS=true ./gradlew --info mailbox-integration-tests:test
db_performance_comparison_test:
extends: .base-test
stage: optional_tests
script:
- OPTIONAL_TESTS=org.briarproject.bramble.db.H2SqliteDatabasePerformanceComparisonTest ./gradlew --info -Djava.security.egd=file:/dev/urandom :bramble-core:test --tests H2SqliteDatabasePerformanceComparisonTest
rules:
- when: manual

View File

@@ -28,11 +28,15 @@
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false" /> <option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false" />
</JavaCodeStyleSettings> </JavaCodeStyleSettings>
<JetCodeStyleSettings> <JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value />
</option>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings> </JetCodeStyleSettings>
<codeStyleSettings language="Groovy"> <codeStyleSettings language="Groovy">
<indentOptions> <indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="USE_TAB_CHARACTER" value="true" /> <option name="USE_TAB_CHARACTER" value="true" />
<option name="SMART_TABS" value="true" /> <option name="SMART_TABS" value="true" />
</indentOptions> </indentOptions>

View File

@@ -4,3 +4,4 @@ build
.settings .settings
src/main/res/raw/*.zip src/main/res/raw/*.zip
src/main/jniLibs src/main/jniLibs
!src/main/jniLibs/.gitkeep

View File

@@ -3,18 +3,20 @@ apply plugin: 'witness'
apply from: 'witness.gradle' apply from: 'witness.gradle'
android { android {
compileSdkVersion 34 compileSdkVersion 33
buildToolsVersion '34.0.0' buildToolsVersion '33.0.0'
packagingOptions { packagingOptions {
doNotStrip '**/*.so' doNotStrip '**/*.so'
} }
defaultConfig { defaultConfig {
// FIXME: sqlite-jdbc-crypt uses __register_atfork which is only available on API >= 23.
// We might be able to solve this by recompiling (or asking upstream to recompile)
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 33 targetSdkVersion 33
versionCode 10514 versionCode 10506
versionName "1.5.14" versionName "1.5.6"
consumerProguardFiles 'proguard-rules.txt' consumerProguardFiles 'proguard-rules.txt'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -37,10 +39,11 @@ android {
configurations { configurations {
tor tor
sqliteJdbcCrypt
} }
dependencies { dependencies {
api 'org.briarproject:dont-kill-me-lib:0.2.8' api 'org.briarproject:dont-kill-me-lib:0.2.7'
// In theory this dependency shouldn't be needed, but without it Android Studio's linter will // In theory this dependency shouldn't be needed, but without it Android Studio's linter will
// complain about unresolved symbols for bramble-api test classes in bramble-android tests, // complain about unresolved symbols for bramble-api test classes in bramble-android tests,
@@ -54,7 +57,10 @@ dependencies {
implementation "org.briarproject:onionwrapper-android:$onionwrapper_version" implementation "org.briarproject:onionwrapper-android:$onionwrapper_version"
tor "org.briarproject:tor-android:$tor_version" tor "org.briarproject:tor-android:$tor_version"
tor "org.briarproject:lyrebird-android:$lyrebird_version" tor "org.briarproject:obfs4proxy-android:$obfs4proxy_version"
tor "org.briarproject:snowflake-android:$snowflake_version"
sqliteJdbcCrypt "io.github.willena:sqlite-jdbc:$sqlite_jdbc_crypt_version"
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version" annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
@@ -68,26 +74,50 @@ dependencies {
testImplementation "org.jmock:jmock-imposters:$jmock_version" testImplementation "org.jmock:jmock-imposters:$jmock_version"
} }
def torLibsDir = 'src/main/jniLibs' def jniLibsDir = 'src/main/jniLibs'
task cleanTorBinaries { task cleanJniLibs {
outputs.dir torLibsDir inputs.dir jniLibsDir
outputs.dir jniLibsDir
doLast { doLast {
delete fileTree(torLibsDir) delete fileTree(jniLibsDir).filter { it.name.endsWith('.so') }
} }
} }
clean.dependsOn cleanTorBinaries clean.dependsOn cleanJniLibs
task unpackTorBinaries { task unpackJniLibs {
outputs.dir torLibsDir outputs.dir jniLibsDir
doLast { doLast {
// Tor
copy { copy {
from configurations.tor.collect { zipTree(it) } from configurations.tor.collect { zipTree(it) }
into torLibsDir into jniLibsDir
}
// sqlite-jdbc-crypt
def archMap = [
aarch64: 'arm64-v8a',
arm : 'armeabi-v7a',
x86 : 'x86',
x86_64 : 'x86_64'
]
configurations.sqliteJdbcCrypt.collect { File artifact ->
zipTree(artifact).each { File f ->
for (String arch : archMap.keySet()) {
if (f.absolutePath.endsWith("/Linux-Android/$arch/libsqlitejdbc.so")) {
def archDir = new File(jniLibsDir, archMap.get(arch))
archDir.mkdirs()
copy {
from f
into archDir
}
break
} }
} }
dependsOn cleanTorBinaries }
}
}
dependsOn cleanJniLibs
} }
preBuild.dependsOn unpackTorBinaries preBuild.dependsOn unpackJniLibs

View File

@@ -6,6 +6,9 @@
-dontwarn org.h2.** -dontwarn org.h2.**
-dontnote org.h2.** -dontnote org.h2.**
# Keep sqlite-jdbc-crypt classes that are loaded via reflection or accessed via JNI
-keep class org.sqlite.** { *; }
-keep class dagger.** { *; } -keep class dagger.** { *; }
-dontwarn dagger.** -dontwarn dagger.**
-dontnote dagger.** -dontnote dagger.**

View File

@@ -8,8 +8,10 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- The BLUETOOTH permission was supposed to be removed in API 31 but is still needed on some Xiaomi/Redmi/POCO devices running API 31 and Nubia devices running API 32/33 --> <!-- The BLUETOOTH permission was supposed to be removed in API 31 but is still needed on some Xiaomi/Redmi/POCO devices running API 31 and Nubia devices running API 32 -->
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission
android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="32" />
<uses-permission <uses-permission
android:name="android.permission.BLUETOOTH_ADMIN" android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" /> android:maxSdkVersion="30" />

View File

@@ -30,7 +30,6 @@ import static android.os.PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED;
import static android.os.PowerManager.ACTION_POWER_SAVE_MODE_CHANGED; import static android.os.PowerManager.ACTION_POWER_SAVE_MODE_CHANGED;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.AndroidUtils.registerReceiver;
class AndroidBatteryManager implements BatteryManager, Service { class AndroidBatteryManager implements BatteryManager, Service {
@@ -53,7 +52,7 @@ class AndroidBatteryManager implements BatteryManager, Service {
public boolean isCharging() { public boolean isCharging() {
// Get the sticky intent for ACTION_BATTERY_CHANGED // Get the sticky intent for ACTION_BATTERY_CHANGED
IntentFilter filter = new IntentFilter(ACTION_BATTERY_CHANGED); IntentFilter filter = new IntentFilter(ACTION_BATTERY_CHANGED);
Intent i = registerReceiver(appContext, null, filter); Intent i = appContext.registerReceiver(null, filter);
if (i == null) return false; if (i == null) return false;
int status = i.getIntExtra(EXTRA_PLUGGED, 0); int status = i.getIntExtra(EXTRA_PLUGGED, 0);
return status != 0; return status != 0;
@@ -72,7 +71,7 @@ class AndroidBatteryManager implements BatteryManager, Service {
filter.addAction(ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED); filter.addAction(ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED);
filter.addAction(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED); filter.addAction(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED);
} }
registerReceiver(appContext, batteryReceiver, filter); appContext.registerReceiver(batteryReceiver, filter);
} }
@Override @Override

View File

@@ -55,7 +55,6 @@ import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.AndroidUtils.registerReceiver;
import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.nullsafety.NullSafety.requireNonNull; import static org.briarproject.nullsafety.NullSafety.requireNonNull;
@@ -104,7 +103,7 @@ class AndroidNetworkManager implements NetworkManager, Service {
filter.addAction(WIFI_AP_STATE_CHANGED_ACTION); filter.addAction(WIFI_AP_STATE_CHANGED_ACTION);
filter.addAction(WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); filter.addAction(WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
if (SDK_INT >= 23) filter.addAction(ACTION_DEVICE_IDLE_MODE_CHANGED); if (SDK_INT >= 23) filter.addAction(ACTION_DEVICE_IDLE_MODE_CHANGED);
registerReceiver(app, networkStateReceiver, filter); app.registerReceiver(networkStateReceiver, filter);
} }
@Override @Override

View File

@@ -56,7 +56,6 @@ import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.AndroidUtils.hasBtConnectPermission; import static org.briarproject.bramble.util.AndroidUtils.hasBtConnectPermission;
import static org.briarproject.bramble.util.AndroidUtils.registerReceiver;
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress; import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@@ -113,7 +112,7 @@ class AndroidBluetoothPlugin extends
filter.addAction(ACTION_STATE_CHANGED); filter.addAction(ACTION_STATE_CHANGED);
filter.addAction(ACTION_SCAN_MODE_CHANGED); filter.addAction(ACTION_SCAN_MODE_CHANGED);
receiver = new BluetoothStateReceiver(); receiver = new BluetoothStateReceiver();
registerReceiver(app, receiver, filter); app.registerReceiver(receiver, filter);
} }
@Override @Override
@@ -238,7 +237,7 @@ class AndroidBluetoothPlugin extends
filter.addAction(ACTION_DISCOVERY_STARTED); filter.addAction(ACTION_DISCOVERY_STARTED);
filter.addAction(ACTION_DISCOVERY_FINISHED); filter.addAction(ACTION_DISCOVERY_FINISHED);
filter.addAction(ACTION_FOUND); filter.addAction(ACTION_FOUND);
registerReceiver(app, receiver, filter); app.registerReceiver(receiver, filter);
try { try {
if (adapter.startDiscovery()) { if (adapter.startDiscovery()) {
long now = clock.currentTimeMillis(); long now = clock.currentTimeMillis();

View File

@@ -201,7 +201,6 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
@Nullable @Nullable
private InetAddress getIpv6AddressForInterface(InetAddress ipv4) { private InetAddress getIpv6AddressForInterface(InetAddress ipv4) {
try { try {
// We may get an NPE from getByInetAddress() on Android 11
NetworkInterface iface = NetworkInterface.getByInetAddress(ipv4); NetworkInterface iface = NetworkInterface.getByInetAddress(ipv4);
if (iface == null) return null; if (iface == null) return null;
for (InetAddress addr : list(iface.getInetAddresses())) { for (InetAddress addr : list(iface.getInetAddresses())) {
@@ -209,7 +208,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
} }
// No suitable address // No suitable address
return null; return null;
} catch (SocketException | NullPointerException e) { } catch (SocketException e) {
logException(LOG, WARNING, e); logException(LOG, WARNING, e);
return null; return null;
} }

View File

@@ -31,6 +31,7 @@ import javax.annotation.concurrent.Immutable;
import javax.inject.Inject; import javax.inject.Inject;
import javax.net.SocketFactory; import javax.net.SocketFactory;
import static android.os.Build.VERSION.SDK_INT;
import static org.briarproject.bramble.util.AndroidUtils.getSupportedArchitectures; import static org.briarproject.bramble.util.AndroidUtils.getSupportedArchitectures;
@Immutable @Immutable
@@ -85,10 +86,15 @@ public class AndroidTorPluginFactory extends TorPluginFactory {
TorWrapper tor = new AndroidTorWrapper(app, wakeLockManager, TorWrapper tor = new AndroidTorWrapper(app, wakeLockManager,
ioExecutor, eventExecutor, architecture, torDirectory, ioExecutor, eventExecutor, architecture, torDirectory,
torSocksPort, torControlPort); torSocksPort, torControlPort);
// Android versions 7.1 and newer can verify Let's Encrypt TLS certs
// signed with the IdentTrust DST Root X3 certificate. Older versions
// of Android consider the certificate to have expired at the end of
// September 2021.
boolean canVerifyLetsEncryptCerts = SDK_INT >= 25;
return new TorPlugin(ioExecutor, wakefulIoExecutor, return new TorPlugin(ioExecutor, wakefulIoExecutor,
networkManager, locationUtils, torSocketFactory, networkManager, locationUtils, torSocketFactory,
circumventionProvider, batteryManager, backoff, circumventionProvider, batteryManager, backoff,
torRendezvousCrypto, tor, callback, MAX_LATENCY, torRendezvousCrypto, tor, callback, MAX_LATENCY,
MAX_IDLE_TIME); MAX_IDLE_TIME, canVerifyLetsEncryptCerts);
} }
} }

View File

@@ -2,10 +2,7 @@ package org.briarproject.bramble.util;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build; import android.os.Build;
import android.os.Looper; import android.os.Looper;
import android.provider.Settings; import android.provider.Settings;
@@ -24,7 +21,6 @@ import javax.annotation.Nullable;
import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_CONNECT;
import static android.app.PendingIntent.FLAG_IMMUTABLE; import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.content.Context.MODE_PRIVATE; import static android.content.Context.MODE_PRIVATE;
import static android.content.Context.RECEIVER_NOT_EXPORTED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static android.os.Process.myPid; import static android.os.Process.myPid;
@@ -68,16 +64,11 @@ public class AndroidUtils {
} }
// Return the address from settings if it's valid and not fake // Return the address from settings if it's valid and not fake
if (SDK_INT < 33) { if (SDK_INT < 33) {
try {
address = Settings.Secure.getString(ctx.getContentResolver(), address = Settings.Secure.getString(ctx.getContentResolver(),
"bluetooth_address"); "bluetooth_address");
if (isValidBluetoothAddress(address)) { if (isValidBluetoothAddress(address)) {
return new Pair<>(address, "settings"); return new Pair<>(address, "settings");
} }
} catch (SecurityException e) {
// Some custom ROMs throw this exception on SDK_INT < 33.
// Fall through
}
} }
// Try to get the address via reflection // Try to get the address via reflection
address = getBluetoothAddressByReflection(adapter); address = getBluetoothAddressByReflection(adapter);
@@ -145,20 +136,4 @@ public class AndroidUtils {
} }
return flags; return flags;
} }
/**
* Could be replaced to a similar call in ContextCompat once we
* use and upgrade to version 1.9.0 or higher of the AndroidX Core library.
*/
@Nullable
@SuppressLint("UnspecifiedRegisterReceiverFlag") // we specify where needed
public static Intent registerReceiver(Context ctx,
@Nullable BroadcastReceiver receiver, IntentFilter filter) {
if (SDK_INT >= 33) {
return ctx.registerReceiver(receiver, filter,
RECEIVER_NOT_EXPORTED);
} else {
return ctx.registerReceiver(receiver, filter);
}
}
} }

View File

@@ -4,18 +4,21 @@ dependencyVerification {
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db', 'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79', 'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7', 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger-compiler:2.51.1:dagger-compiler-2.51.1.jar:14cf2def1c4c8cd3b977840e297b463191d537cd1c8330992ca5c0b341a641ad', 'com.google.dagger:dagger-compiler:2.45:dagger-compiler-2.45.jar:5617dfb994537dba5b41f3744a6dd13ec3cd99789c065e0d5c6fa9f21cf7ca25',
'com.google.dagger:dagger-spi:2.51.1:dagger-spi-2.51.1.jar:deb52030b92b27c5dcd76b2c0747f1cf105b60939f6073b43eb06cfe7c9ba601', 'com.google.dagger:dagger-producers:2.45:dagger-producers-2.45.jar:a05abb4c3ccf6bb0f056bdcb5ef973898ecf172952ab5948a824aeea6c86ecaa',
'com.google.dagger:dagger:2.51.1:dagger-2.51.1.jar:c3891a4c4a4e48682888ca321eaf8497004b286e1d9a2936867373219f7dd86d', 'com.google.dagger:dagger-spi:2.45:dagger-spi-2.45.jar:7cd6f0b09d88e64a9c97bc80e544ab8ac8fdee9301754413585a74cf64222b27',
'com.google.devtools.ksp:symbol-processing-api:1.9.20-1.0.14:symbol-processing-api-1.9.20-1.0.14.jar:d0339396f40dc9eb3b3f7bc86257f93869ee23448fa31ec4a1de900c6b7ae6d7', 'com.google.dagger:dagger:2.45:dagger-2.45.jar:f011cae7d2c0fb7ea17c34e05bc10e768b1081a5892ad019cf1fdb0e125c49c1',
'com.google.errorprone:error_prone_annotations:2.23.0:error_prone_annotations-2.23.0.jar:ec6f39f068b6ff9ac323c68e28b9299f8c0a80ca512dccb1d4a70f40ac3ec054', 'com.google.devtools.ksp:symbol-processing-api:1.7.0-1.0.6:symbol-processing-api-1.7.0-1.0.6.jar:adc29417be5ca9ff42118105fea4e36d9ef44987abfc41432309371a60198941',
'com.google.errorprone:error_prone_annotations:2.7.1:error_prone_annotations-2.7.1.jar:cd5257c08a246cf8628817ae71cb822be192ef91f6881ca4a3fcff4f1de1cff3',
'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30', 'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30',
'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e', 'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e',
'com.google.guava:failureaccess:1.0.2:failureaccess-1.0.2.jar:8a8f81cf9b359e3f6dfa691a1e776985c061ef2f223c9b2c80753e1b458e8064', 'com.google.guava:failureaccess:1.0.1:failureaccess-1.0.1.jar:a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26',
'com.google.guava:guava:33.0.0-jre:guava-33.0.0-jre.jar:f4d85c3e4d411694337cb873abea09b242b664bb013320be6105327c45991537', 'com.google.guava:guava:31.0.1-jre:guava-31.0.1-jre.jar:d5be94d65e87bd219fb3193ad1517baa55a3b88fc91d21cf735826ab5af087b9',
'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99', 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
'com.google.j2objc:j2objc-annotations:1.3:j2objc-annotations-1.3.jar:21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b',
'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291', 'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
'com.squareup:kotlinpoet:1.11.0:kotlinpoet-1.11.0.jar:2887ada1ca03dd83baa2758640d87e840d1907564db0ef88d2289c868a980492', 'com.squareup:kotlinpoet:1.11.0:kotlinpoet-1.11.0.jar:2887ada1ca03dd83baa2758640d87e840d1907564db0ef88d2289c868a980492',
'io.github.willena:sqlite-jdbc:3.41.2.1:sqlite-jdbc-3.41.2.1.jar:fb60e7137c1791db89240701338d31ca42a0bec5508c1aab1c1131cf885f2309',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f', 'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3', 'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3',
@@ -23,29 +26,32 @@ dependencyVerification {
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0', 'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd', 'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047', 'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
'org.briarproject:dont-kill-me-lib:0.2.8:dont-kill-me-lib-0.2.8.aar:e21173e480ee3f2364c142cc14db8dc6447be91bde9e62e4985c485ea0af9126', 'org.briarproject:dont-kill-me-lib:0.2.7:dont-kill-me-lib-0.2.7.aar:8a9540941fd927e1c127096a7a9b4aa61ce2f2965d2e24f849be92f9e57213c4',
'org.briarproject:jtorctl:0.5:jtorctl-0.5.jar:43f8c7d390169772b9a2c82ab806c8414c136a2a8636c555e22754bb7260793b', 'org.briarproject:jtorctl:0.5:jtorctl-0.5.jar:43f8c7d390169772b9a2c82ab806c8414c136a2a8636c555e22754bb7260793b',
'org.briarproject:lyrebird-android:0.5.0-3:lyrebird-android-0.5.0-3.jar:67e21cbbfda0b17ab9e0741ada170c606ddda4e9548a70c421aa83b907ebb714',
'org.briarproject:null-safety:0.1:null-safety-0.1.jar:161760de5e838cb982bafa973df820675d4397098e9a91637a36a306d43ba011', 'org.briarproject:null-safety:0.1:null-safety-0.1.jar:161760de5e838cb982bafa973df820675d4397098e9a91637a36a306d43ba011',
'org.briarproject:onionwrapper-android:0.1.3:onionwrapper-android-0.1.3.aar:15231f0b2ad44df8eb1dd362a989ba3f88ebdc9b02a9128daa72a8da83651bf0', 'org.briarproject:obfs4proxy-android:0.0.14-tor2:obfs4proxy-android-0.0.14-tor2.jar:a0a93770d6760ce57d9dbd31cc7177687374e00c3361dac22ab75e3b6e0f289e',
'org.briarproject:onionwrapper-core:0.1.3:onionwrapper-core-0.1.3.jar:32d08c9d81a9591e08d7e64e3569334fee21f503b00514006f2e6cbbd409d0df', 'org.briarproject:onionwrapper-android:0.0.5:onionwrapper-android-0.0.5.aar:d761854dac454616b3e0ca099b2cd17060365ce4316afe495cc7ae86b6c81d15',
'org.briarproject:tor-android:0.4.8.14:tor-android-0.4.8.14.jar:fc7c4f5007a98132ba84534a873f101951d2d554d5da5f2031b85c277f8617a6', 'org.briarproject:onionwrapper-core:0.0.5:onionwrapper-core-0.0.5.jar:9071678323535cb3dfe0f3add96066037db43ea024333eba0117c759bcbd8d63',
'org.briarproject:snowflake-android:2.5.1:snowflake-android-2.5.1.jar:88ec81c17b1b6fa884d06839dec0330e328b45c89f88c970a213ce91ca8eac87',
'org.briarproject:tor-android:0.4.7.14:tor-android-0.4.7.14.jar:d39faa3a8abb116136c191c6ebadf8ea0e1f3e4785076d2c66a7b3b0f26988a2',
'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a', 'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a',
'org.checkerframework:checker-qual:3.41.0:checker-qual-3.41.0.jar:2f9f245bf68e4259d610894f2406dc1f6363dc639302bd566e8272e4f4541172', 'org.checkerframework:checker-qual:3.12.0:checker-qual-3.12.0.jar:ff10785ac2a357ec5de9c293cb982a2cbb605c0309ea4cc1cb9b9bc6dbe7f3cb',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9', 'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21', 'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050', 'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
'org.jacoco:org.jacoco.agent:0.8.7:org.jacoco.agent-0.8.7.jar:9cbcc986e0fbe821a78ff1f8f7d5216f200e5eb124e7f6837d1dc4a77b28b143', 'org.jacoco:org.jacoco.agent:0.8.8:org.jacoco.agent-0.8.8.jar:072ecbd496896623899a696fff12c01c1615f737616d2792e6d0e10cdf8a610d',
'org.jacoco:org.jacoco.ant:0.8.7:org.jacoco.ant-0.8.7.jar:97ca96a382c3f23a44d8eb4c4e6c3742a30cb8005774a76ced0fc4806ce49605', 'org.jacoco:org.jacoco.ant:0.8.8:org.jacoco.ant-0.8.8.jar:02e33bd2c48dc0be67c2fea84d43beececfd400da6797c58153253d4c30aca15',
'org.jacoco:org.jacoco.core:0.8.7:org.jacoco.core-0.8.7.jar:ad7739b5fb5969aa1a8aead3d74ed54dc82ed012f1f10f336bd1b96e71c1a13c', 'org.jacoco:org.jacoco.core:0.8.8:org.jacoco.core-0.8.8.jar:474c782f809d88924713dfdbf0acb79d330f904be576484803463d0465611643',
'org.jacoco:org.jacoco.report:0.8.7:org.jacoco.report-0.8.7.jar:cc89258623700a6c932592153cb528785876b6da183d5431f97efbba6f020e5b', 'org.jacoco:org.jacoco.report:0.8.8:org.jacoco.report-0.8.8.jar:2c129110f3e3fcaa1f8179578ea3894586199cb0826be5c7790278084c9622a9',
'org.jetbrains.kotlin:kotlin-reflect:1.6.10:kotlin-reflect-1.6.10.jar:3277ac102ae17aad10a55abec75ff5696c8d109790396434b496e75087854203', 'org.jetbrains.kotlin:kotlin-reflect:1.6.10:kotlin-reflect-1.6.10.jar:3277ac102ae17aad10a55abec75ff5696c8d109790396434b496e75087854203',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.9.10:kotlin-stdlib-common-1.9.10.jar:cde3341ba18a2ba262b0b7cf6c55b20c90e8d434e42c9a13e6a3f770db965a88', 'org.jetbrains.kotlin:kotlin-stdlib-common:1.7.0:kotlin-stdlib-common-1.7.0.jar:59c6ff64fe9a6604afce03e8aaa75f83586c6030ac71fb0b34ee7cdefed3618f',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0:kotlin-stdlib-jdk7-1.9.0.jar:b7979a7aac94055f0d9f1fd3b47ce5ffe1cb6032a842ba9fbe7186f085289178', 'org.jetbrains.kotlin:kotlin-stdlib-common:1.8.0:kotlin-stdlib-common-1.8.0.jar:78ef93b59e603cc0fe51def9bd4c037b07cbace3b3b7806d1a490a42bc1f4cb2',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.10:kotlin-stdlib-jdk7-1.9.10.jar:ac6361bf9ad1ed382c2103d9712c47cdec166232b4903ed596e8876b0681c9b7', 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.0:kotlin-stdlib-jdk7-1.7.0.jar:07e91be9b2ca20672d2bdb7e181b766e73453a2da13492b5ddaee8fa47aea239',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0:kotlin-stdlib-jdk8-1.9.0.jar:a59fa24fdf1ffb594baecdbf0fd10010f977cea10236d487fe3464977a7377fa', 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0:kotlin-stdlib-jdk7-1.8.0.jar:4c889d1d9803f5f2eb6c1592a6b7e62369ac7660c9eee15aba16fec059163666',
'org.jetbrains.kotlin:kotlin-stdlib:1.9.10:kotlin-stdlib-1.9.10.jar:55e989c512b80907799f854309f3bc7782c5b3d13932442d0379d5c472711504', 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.0:kotlin-stdlib-jdk8-1.7.0.jar:cf058e11db1dfc9944680c8c61b95ac689aaaa8a3eb30bced028100f038f030b',
'org.jetbrains.kotlin:kotlin-stdlib:1.9.20:kotlin-stdlib-1.9.20.jar:28a35bcdff46d864f80f346a617e486284b208d17378c41900dfb1de95a90e6c', 'org.jetbrains.kotlin:kotlin-stdlib:1.7.0:kotlin-stdlib-1.7.0.jar:aa88e9625577957f3249a46cb6e166ee09b369e600f7a11d148d16b0a6d87f05',
'org.jetbrains.kotlin:kotlin-stdlib:1.8.0:kotlin-stdlib-1.8.0.jar:c77bef8774640b9fb9d6e217459ff220dae59878beb7d2e4b430506feffc654e',
'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.5.0:kotlinx-metadata-jvm-0.5.0.jar:ca063a96639b08b9eaa0de4d65e899480740a6efbe28ab9a8681a2ced03055a4',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478', 'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09', 'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b', 'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',
@@ -53,10 +59,10 @@ dependencyVerification {
'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04', 'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04',
'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be', 'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be',
'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984', 'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.ow2.asm:asm-analysis:9.1:asm-analysis-9.1.jar:81a88041b1b8beda5a8a99646098046c48709538270c49def68abff25ac3be34', 'org.ow2.asm:asm-analysis:9.2:asm-analysis-9.2.jar:878fbe521731c072d14d2d65b983b1beae6ad06fda0007b6a8bae81f73f433c4',
'org.ow2.asm:asm-commons:9.1:asm-commons-9.1.jar:afcb26dc1fc12c0c4a99ada670908dd82e18dfc488caf5ee92546996b470c00c', 'org.ow2.asm:asm-commons:9.2:asm-commons-9.2.jar:be4ce53138a238bb522cd781cf91f3ba5ce2f6ca93ec62d46a162a127225e0a6',
'org.ow2.asm:asm-tree:9.1:asm-tree-9.1.jar:fd00afa49e9595d7646205b09cecb4a776a8ff0ba06f2d59b8f7bf9c704b4a73', 'org.ow2.asm:asm-tree:9.2:asm-tree-9.2.jar:aabf9bd23091a4ebfc109c1f3ee7cf3e4b89f6ba2d3f51c5243f16b3cffae011',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de', 'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'org.ow2.asm:asm:9.1:asm-9.1.jar:cda4de455fab48ff0bcb7c48b4639447d4de859a7afc30a094a986f0936beba2', 'org.ow2.asm:asm:9.2:asm-9.2.jar:b9d4fe4d71938df38839f0eca42aaaa64cf8b313d678da036f0cb3ca199b47f5',
] ]
} }

View File

@@ -54,6 +54,38 @@ public interface CryptoComponent {
KeyPair ourKeyPair, byte[]... inputs) KeyPair ourKeyPair, byte[]... inputs)
throws GeneralSecurityException; throws GeneralSecurityException;
/**
* Derives a shared secret from two static and two ephemeral key pairs.
* <p>
* Do not use this method for new protocols. The shared secret can be
* re-derived using the ephemeral public keys and both static private
* keys, so keys derived from the shared secret should not be used if
* forward secrecy is required. Use {@link #deriveSharedSecret(String,
* PublicKey, PublicKey, KeyPair, KeyPair, boolean, byte[]...)} instead.
* <p>
* TODO: Remove this after a reasonable migration period (added 2023-03-10).
* <p>
*
* @param label A namespaced label indicating the purpose of this shared
* secret, to prevent it from being repurposed or colliding with a shared
* secret derived for another purpose
* @param theirStaticPublicKey The static public key of the remote party
* @param theirEphemeralPublicKey The ephemeral public key of the remote
* party
* @param ourStaticKeyPair The static key pair of the local party
* @param ourEphemeralKeyPair The ephemeral key pair of the local party
* @param alice True if the local party is Alice
* @param inputs Additional inputs that will be included in the
* derivation of the shared secret
* @return The shared secret
*/
@Deprecated
SecretKey deriveSharedSecretBadly(String label,
PublicKey theirStaticPublicKey, PublicKey theirEphemeralPublicKey,
KeyPair ourStaticKeyPair, KeyPair ourEphemeralKeyPair,
boolean alice, byte[]... inputs)
throws GeneralSecurityException;
/** /**
* Derives a shared secret from two static and two ephemeral key pairs. * Derives a shared secret from two static and two ephemeral key pairs.
* *

View File

@@ -46,7 +46,6 @@ public interface TorConstants {
/** /**
* Reason flag returned by {@link Plugin#getReasonsDisabled()}. * Reason flag returned by {@link Plugin#getReasonsDisabled()}.
* Currently unused, but may be worth keeping for future use.
*/ */
int REASON_COUNTRY_BLOCKED = 8; int REASON_COUNTRY_BLOCKED = 8;
} }

View File

@@ -4,7 +4,7 @@ dependencyVerification {
'com.fasterxml.jackson.core:jackson-annotations:2.13.4:jackson-annotations-2.13.4.jar:ac5b27a634942391ca113850ee7db01df1499a240174021263501c05fc653b44', 'com.fasterxml.jackson.core:jackson-annotations:2.13.4:jackson-annotations-2.13.4.jar:ac5b27a634942391ca113850ee7db01df1499a240174021263501c05fc653b44',
'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79', 'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7', 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger:2.51.1:dagger-2.51.1.jar:c3891a4c4a4e48682888ca321eaf8497004b286e1d9a2936867373219f7dd86d', 'com.google.dagger:dagger:2.45:dagger-2.45.jar:f011cae7d2c0fb7ea17c34e05bc10e768b1081a5892ad019cf1fdb0e125c49c1',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3', 'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3',
'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11', 'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11',

View File

@@ -16,6 +16,7 @@ dependencies {
implementation "org.bouncycastle:bcprov-jdk15to18:$bouncy_castle_version" implementation "org.bouncycastle:bcprov-jdk15to18:$bouncy_castle_version"
//noinspection GradleDependency //noinspection GradleDependency
implementation 'com.h2database:h2:1.4.192' // The last version that supports Java 1.6 implementation 'com.h2database:h2:1.4.192' // The last version that supports Java 1.6
implementation "io.github.willena:sqlite-jdbc:$sqlite_jdbc_crypt_version"
implementation 'org.bitlet:weupnp:0.1.4' implementation 'org.bitlet:weupnp:0.1.4'
implementation 'net.i2p.crypto:eddsa:0.2.0' implementation 'net.i2p.crypto:eddsa:0.2.0'
implementation 'org.whispersystems:curve25519-java:0.5.0' implementation 'org.whispersystems:curve25519-java:0.5.0'

View File

@@ -14,6 +14,16 @@ interface HandshakeConstants {
*/ */
byte PROTOCOL_MINOR_VERSION = 1; byte PROTOCOL_MINOR_VERSION = 1;
/**
* Label for deriving the master key when using the deprecated v0.0 key
* derivation method.
* <p>
* TODO: Remove this after a reasonable migration period (added 2023-03-10).
*/
@Deprecated
String MASTER_KEY_LABEL_0_0 =
"org.briarproject.bramble.handshake/MASTER_KEY";
/** /**
* Label for deriving the master key when using the v0.1 key derivation * Label for deriving the master key when using the v0.1 key derivation
* method. * method.

View File

@@ -12,6 +12,20 @@ interface HandshakeCrypto {
KeyPair generateEphemeralKeyPair(); KeyPair generateEphemeralKeyPair();
/**
* Derives the master key from the given static and ephemeral keys using
* the deprecated v0.0 key derivation method.
* <p>
* TODO: Remove this after a reasonable migration period (added 2023-03-10).
*
* @param alice Whether the local peer is Alice
*/
@Deprecated
SecretKey deriveMasterKey_0_0(PublicKey theirStaticPublicKey,
PublicKey theirEphemeralPublicKey, KeyPair ourStaticKeyPair,
KeyPair ourEphemeralKeyPair, boolean alice)
throws GeneralSecurityException;
/** /**
* Derives the master key from the given static and ephemeral keys using * Derives the master key from the given static and ephemeral keys using
* the v0.1 key derivation method. * the v0.1 key derivation method.

View File

@@ -13,6 +13,7 @@ import javax.inject.Inject;
import static org.briarproject.bramble.contact.HandshakeConstants.ALICE_PROOF_LABEL; import static org.briarproject.bramble.contact.HandshakeConstants.ALICE_PROOF_LABEL;
import static org.briarproject.bramble.contact.HandshakeConstants.BOB_PROOF_LABEL; import static org.briarproject.bramble.contact.HandshakeConstants.BOB_PROOF_LABEL;
import static org.briarproject.bramble.contact.HandshakeConstants.MASTER_KEY_LABEL_0_0;
import static org.briarproject.bramble.contact.HandshakeConstants.MASTER_KEY_LABEL_0_1; import static org.briarproject.bramble.contact.HandshakeConstants.MASTER_KEY_LABEL_0_1;
@Immutable @Immutable
@@ -31,6 +32,27 @@ class HandshakeCryptoImpl implements HandshakeCrypto {
return crypto.generateAgreementKeyPair(); return crypto.generateAgreementKeyPair();
} }
@Override
@Deprecated
public SecretKey deriveMasterKey_0_0(PublicKey theirStaticPublicKey,
PublicKey theirEphemeralPublicKey, KeyPair ourStaticKeyPair,
KeyPair ourEphemeralKeyPair, boolean alice) throws
GeneralSecurityException {
byte[] theirStatic = theirStaticPublicKey.getEncoded();
byte[] theirEphemeral = theirEphemeralPublicKey.getEncoded();
byte[] ourStatic = ourStaticKeyPair.getPublic().getEncoded();
byte[] ourEphemeral = ourEphemeralKeyPair.getPublic().getEncoded();
byte[][] inputs = {
alice ? ourStatic : theirStatic,
alice ? theirStatic : ourStatic,
alice ? ourEphemeral : theirEphemeral,
alice ? theirEphemeral : ourEphemeral
};
return crypto.deriveSharedSecretBadly(MASTER_KEY_LABEL_0_0,
theirStaticPublicKey, theirEphemeralPublicKey,
ourStaticKeyPair, ourEphemeralKeyPair, alice, inputs);
}
@Override @Override
public SecretKey deriveMasterKey_0_1(PublicKey theirStaticPublicKey, public SecretKey deriveMasterKey_0_1(PublicKey theirStaticPublicKey,
PublicKey theirEphemeralPublicKey, KeyPair ourStaticKeyPair, PublicKey theirEphemeralPublicKey, KeyPair ourStaticKeyPair,

View File

@@ -2,7 +2,6 @@ package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.Pair; import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.UnsupportedVersionException;
import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.contact.HandshakeManager; import org.briarproject.bramble.api.contact.HandshakeManager;
import org.briarproject.bramble.api.contact.PendingContact; import org.briarproject.bramble.api.contact.PendingContact;
@@ -112,12 +111,21 @@ class HandshakeManagerImpl implements HandshakeManager {
sendMinorVersion(recordWriter); sendMinorVersion(recordWriter);
sendPublicKey(recordWriter, ourEphemeralKeyPair.getPublic()); sendPublicKey(recordWriter, ourEphemeralKeyPair.getPublic());
} }
byte theirMinorVersion = theirMinorVersionAndKey.getFirst();
PublicKey theirEphemeralPublicKey = theirMinorVersionAndKey.getSecond(); PublicKey theirEphemeralPublicKey = theirMinorVersionAndKey.getSecond();
SecretKey masterKey; SecretKey masterKey;
try { try {
if (theirMinorVersion > 0) {
masterKey = handshakeCrypto.deriveMasterKey_0_1( masterKey = handshakeCrypto.deriveMasterKey_0_1(
theirStaticPublicKey, theirEphemeralPublicKey, theirStaticPublicKey, theirEphemeralPublicKey,
ourStaticKeyPair, ourEphemeralKeyPair, alice); ourStaticKeyPair, ourEphemeralKeyPair, alice);
} else {
// TODO: Remove this branch after a reasonable migration
// period (added 2023-03-10).
masterKey = handshakeCrypto.deriveMasterKey_0_0(
theirStaticPublicKey, theirEphemeralPublicKey,
ourStaticKeyPair, ourEphemeralKeyPair, alice);
}
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throw new FormatException(); throw new FormatException();
} }
@@ -179,11 +187,10 @@ class HandshakeManagerImpl implements HandshakeManager {
} else { } else {
// The remote peer did not send a minor version record, so the // The remote peer did not send a minor version record, so the
// remote peer's protocol minor version is assumed to be zero // remote peer's protocol minor version is assumed to be zero
// TODO: Remove this branch after a reasonable migration period
// TODO: How communicate to user that contact seems to use a version // (added 2023-03-10).
// of Briar that is too old? (be aware of MITM attacks) theirMinorVersion = 0;
// `RendezvousPollerImpl` broadcasts PendingContactState FAILED via EventBus theirEphemeralPublicKey = parsePublicKey(first);
throw new UnsupportedVersionException(true);
} }
return new Pair<>(theirMinorVersion, theirEphemeralPublicKey); return new Pair<>(theirMinorVersion, theirEphemeralPublicKey);
} }

View File

@@ -222,6 +222,36 @@ class CryptoComponentImpl implements CryptoComponent {
return new SecretKey(hash); return new SecretKey(hash);
} }
@Override
@Deprecated
public SecretKey deriveSharedSecretBadly(String label,
PublicKey theirStaticPublicKey, PublicKey theirEphemeralPublicKey,
KeyPair ourStaticKeyPair, KeyPair ourEphemeralKeyPair,
boolean alice, byte[]... inputs) throws GeneralSecurityException {
PrivateKey ourStaticPrivateKey = ourStaticKeyPair.getPrivate();
PrivateKey ourEphemeralPrivateKey = ourEphemeralKeyPair.getPrivate();
byte[][] hashInputs = new byte[inputs.length + 3][];
// Alice static/Bob static
hashInputs[0] = performRawKeyAgreement(ourStaticPrivateKey,
theirStaticPublicKey);
// Alice static/Bob ephemeral, Bob static/Alice ephemeral
if (alice) {
hashInputs[1] = performRawKeyAgreement(ourStaticPrivateKey,
theirEphemeralPublicKey);
hashInputs[2] = performRawKeyAgreement(ourEphemeralPrivateKey,
theirStaticPublicKey);
} else {
hashInputs[1] = performRawKeyAgreement(ourEphemeralPrivateKey,
theirStaticPublicKey);
hashInputs[2] = performRawKeyAgreement(ourStaticPrivateKey,
theirEphemeralPublicKey);
}
arraycopy(inputs, 0, hashInputs, 3, inputs.length);
byte[] hash = hash(label, hashInputs);
if (hash.length != SecretKey.LENGTH) throw new IllegalStateException();
return new SecretKey(hash);
}
@Override @Override
public SecretKey deriveSharedSecret(String label, public SecretKey deriveSharedSecret(String label,
PublicKey theirStaticPublicKey, PublicKey theirEphemeralPublicKey, PublicKey theirStaticPublicKey, PublicKey theirEphemeralPublicKey,

View File

@@ -413,6 +413,9 @@ interface Database<T> {
*/ */
Collection<MessageId> getMessageIds(T txn, GroupId g) throws DbException; Collection<MessageId> getMessageIds(T txn, GroupId g) throws DbException;
Collection<String> explainGetMessageIds(T txn, GroupId g)
throws DbException;
/** /**
* Returns the IDs of any delivered messages in the given group with * Returns the IDs of any delivered messages in the given group with
* metadata that matches all entries in the given query. If the query is * metadata that matches all entries in the given query. If the query is

View File

@@ -24,7 +24,7 @@ public class DatabaseModule {
@Singleton @Singleton
Database<Connection> provideDatabase(DatabaseConfig config, Database<Connection> provideDatabase(DatabaseConfig config,
MessageFactory messageFactory, Clock clock) { MessageFactory messageFactory, Clock clock) {
return new H2Database(config, messageFactory, clock); return new SqliteDatabase(config, messageFactory, clock);
} }
@Provides @Provides

View File

@@ -4,14 +4,16 @@ class DatabaseTypes {
private final String hashType, secretType, binaryType; private final String hashType, secretType, binaryType;
private final String counterType, stringType; private final String counterType, stringType;
private final String explainCommand; // FIXME: Remove
public DatabaseTypes(String hashType, String secretType, String binaryType, public DatabaseTypes(String hashType, String secretType, String binaryType,
String counterType, String stringType) { String counterType, String stringType, String explainCommand) {
this.hashType = hashType; this.hashType = hashType;
this.secretType = secretType; this.secretType = secretType;
this.binaryType = binaryType; this.binaryType = binaryType;
this.counterType = counterType; this.counterType = counterType;
this.stringType = stringType; this.stringType = stringType;
this.explainCommand = explainCommand;
} }
/** /**
@@ -22,6 +24,7 @@ class DatabaseTypes {
* <li> _BINARY * <li> _BINARY
* <li> _COUNTER * <li> _COUNTER
* <li> _STRING * <li> _STRING
* <li> _EXPLAIN
*/ */
String replaceTypes(String s) { String replaceTypes(String s) {
s = s.replaceAll("_HASH", hashType); s = s.replaceAll("_HASH", hashType);
@@ -29,6 +32,7 @@ class DatabaseTypes {
s = s.replaceAll("_BINARY", binaryType); s = s.replaceAll("_BINARY", binaryType);
s = s.replaceAll("_COUNTER", counterType); s = s.replaceAll("_COUNTER", counterType);
s = s.replaceAll("_STRING", stringType); s = s.replaceAll("_STRING", stringType);
s = s.replaceAll("_EXPLAIN", explainCommand);
return s; return s;
} }
} }

View File

@@ -39,10 +39,13 @@ class H2Database extends JdbcDatabase {
private static final String HASH_TYPE = "BINARY(32)"; private static final String HASH_TYPE = "BINARY(32)";
private static final String SECRET_TYPE = "BINARY(32)"; private static final String SECRET_TYPE = "BINARY(32)";
private static final String BINARY_TYPE = "BINARY"; private static final String BINARY_TYPE = "BINARY";
private static final String COUNTER_TYPE = "INT NOT NULL AUTO_INCREMENT"; private static final String COUNTER_TYPE =
"INT NOT NULL AUTO_INCREMENT PRIMARY KEY";
private static final String STRING_TYPE = "VARCHAR"; private static final String STRING_TYPE = "VARCHAR";
private static final String EXPLAIN_COMMAND = "EXPLAIN";
private static final DatabaseTypes dbTypes = new DatabaseTypes(HASH_TYPE, private static final DatabaseTypes dbTypes = new DatabaseTypes(HASH_TYPE,
SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE); SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE,
EXPLAIN_COMMAND);
private final DatabaseConfig config; private final DatabaseConfig config;
private final String url; private final String url;
@@ -73,7 +76,7 @@ class H2Database extends JdbcDatabase {
boolean reopen = isNonEmptyDirectory(dir); boolean reopen = isNonEmptyDirectory(dir);
if (LOG.isLoggable(INFO)) LOG.info("Reopening DB: " + reopen); if (LOG.isLoggable(INFO)) LOG.info("Reopening DB: " + reopen);
if (!reopen && dir.mkdirs()) LOG.info("Created database directory"); if (!reopen && dir.mkdirs()) LOG.info("Created database directory");
super.open("org.h2.Driver", reopen, key, listener); super.open("org.h2.Driver", reopen, false, key, listener);
if (LOG.isLoggable(INFO)) { if (LOG.isLoggable(INFO)) {
LOG.info("Contents of account directory after opening DB:"); LOG.info("Contents of account directory after opening DB:");
logFileOrDir(LOG, INFO, dir.getParentFile()); logFileOrDir(LOG, INFO, dir.getParentFile());
@@ -89,17 +92,11 @@ class H2Database extends JdbcDatabase {
try { try {
c = createConnection(); c = createConnection();
closeAllConnections(); closeAllConnections();
LOG.info("Compacting DB"); setDirty(c, false);
s = c.createStatement(); s = c.createStatement();
s.execute("SHUTDOWN COMPACT"); s.execute("SHUTDOWN COMPACT");
LOG.info("Finished compacting DB");
s.close(); s.close();
c.close(); c.close();
// Reopen the DB to mark it as clean after compacting
c = createConnection();
setDirty(c, false);
LOG.info("Marked DB as clean");
c.close();
} catch (SQLException e) { } catch (SQLException e) {
tryToClose(s, LOG, WARNING); tryToClose(s, LOG, WARNING);
tryToClose(c, LOG, WARNING); tryToClose(c, LOG, WARNING);
@@ -132,7 +129,6 @@ class H2Database extends JdbcDatabase {
closeAllConnections(); closeAllConnections();
s = c.createStatement(); s = c.createStatement();
s.execute("SHUTDOWN COMPACT"); s.execute("SHUTDOWN COMPACT");
LOG.info("Finished compacting DB");
s.close(); s.close();
c.close(); c.close();
} catch (SQLException e) { } catch (SQLException e) {

View File

@@ -38,11 +38,13 @@ class HyperSqlDatabase extends JdbcDatabase {
private static final String HASH_TYPE = "BINARY(32)"; private static final String HASH_TYPE = "BINARY(32)";
private static final String SECRET_TYPE = "BINARY(32)"; private static final String SECRET_TYPE = "BINARY(32)";
private static final String BINARY_TYPE = "BINARY"; private static final String BINARY_TYPE = "BINARY";
private static final String COUNTER_TYPE = private static final String COUNTER_TYPE = "INTEGER NOT NULL"
"INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY(START WITH 1)"; + " PRIMARY KEY GENERATED ALWAYS AS IDENTITY(START WITH 1)";
private static final String STRING_TYPE = "VARCHAR"; private static final String STRING_TYPE = "VARCHAR";
private static final String EXPLAIN_COMMAND = "EXPLAIN PLAN FOR";
private static final DatabaseTypes dbTypes = new DatabaseTypes(HASH_TYPE, private static final DatabaseTypes dbTypes = new DatabaseTypes(HASH_TYPE,
SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE); SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE,
EXPLAIN_COMMAND);
private final DatabaseConfig config; private final DatabaseConfig config;
private final String url; private final String url;
@@ -70,7 +72,7 @@ class HyperSqlDatabase extends JdbcDatabase {
boolean reopen = isNonEmptyDirectory(dir); boolean reopen = isNonEmptyDirectory(dir);
if (LOG.isLoggable(INFO)) LOG.info("Reopening DB: " + reopen); if (LOG.isLoggable(INFO)) LOG.info("Reopening DB: " + reopen);
if (!reopen && dir.mkdirs()) LOG.info("Created database directory"); if (!reopen && dir.mkdirs()) LOG.info("Created database directory");
super.open("org.hsqldb.jdbc.JDBCDriver", reopen, key, listener); super.open("org.hsqldb.jdbc.JDBCDriver", reopen, true, key, listener);
return reopen; return reopen;
} }

View File

@@ -143,8 +143,7 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " handshakePublicKey _BINARY," // Null if key is unknown + " handshakePublicKey _BINARY," // Null if key is unknown
+ " localAuthorId _HASH NOT NULL," + " localAuthorId _HASH NOT NULL,"
+ " verified BOOLEAN NOT NULL," + " verified BOOLEAN NOT NULL,"
+ " syncVersions _BINARY DEFAULT '00' NOT NULL," + " syncVersions _BINARY DEFAULT x'00' NOT NULL,"
+ " PRIMARY KEY (contactId),"
+ " FOREIGN KEY (localAuthorId)" + " FOREIGN KEY (localAuthorId)"
+ " REFERENCES localAuthors (authorId)" + " REFERENCES localAuthors (authorId)"
+ " ON DELETE CASCADE)"; + " ON DELETE CASCADE)";
@@ -295,11 +294,11 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " active BOOLEAN NOT NULL," + " active BOOLEAN NOT NULL,"
+ " rootKey _SECRET," // Null for rotation keys + " rootKey _SECRET," // Null for rotation keys
+ " alice BOOLEAN," // Null for rotation keys + " alice BOOLEAN," // Null for rotation keys
+ " PRIMARY KEY (transportId, keySetId)," // FIXME: Primary key has changed, migration needed
+ " FOREIGN KEY (transportId)" + " FOREIGN KEY (transportId)"
+ " REFERENCES transports (transportId)" + " REFERENCES transports (transportId)"
+ " ON DELETE CASCADE," + " ON DELETE CASCADE,"
+ " UNIQUE (keySetId)," // FIXME: Unique constraint removed, migration needed
+ " FOREIGN KEY (contactId)" + " FOREIGN KEY (contactId)"
+ " REFERENCES contacts (contactId)" + " REFERENCES contacts (contactId)"
+ " ON DELETE CASCADE," + " ON DELETE CASCADE,"
@@ -358,6 +357,85 @@ abstract class JdbcDatabase implements Database<Connection> {
"CREATE INDEX IF NOT EXISTS messagesByCleanupDeadline" "CREATE INDEX IF NOT EXISTS messagesByCleanupDeadline"
+ " ON messages (cleanupDeadline)"; + " ON messages (cleanupDeadline)";
// FIXME: Migration needs to add new index
private static final String INDEX_OUTGOING_KEYS_BY_TRANSPORT_ID_KEY_SET_ID =
"CREATE INDEX IF NOT EXISTS outgoingKeysByTransportIdKeySetId"
+ " ON outgoingKeys (transportId, keySetId)";
private static final String FOREIGN_INDEX_CONTACTS_BY_LOCAL_AUTHOR_ID =
"CREATE INDEX IF NOT EXISTS contactsByLocalAuthorId"
+ " ON contacts (localAuthorId)";
private static final String FOREIGN_INDEX_GROUP_METADATA_BY_GROUP_ID =
"CREATE INDEX IF NOT EXISTS groupMetadataByGroupId"
+ " ON groupMetadata (groupId)";
private static final String FOREIGN_INDEX_GROUP_VISIBILITIES_BY_CONTACT_ID =
"CREATE INDEX IF NOT EXISTS groupVisibilitiesByContactId"
+ " ON groupVisibilities (contactId)";
private static final String FOREIGN_INDEX_GROUP_VISIBILITIES_BY_GROUP_ID =
"CREATE INDEX IF NOT EXISTS groupVisibilitiesByGroupId"
+ " ON groupVisibilities (groupId)";
private static final String FOREIGN_INDEX_MESSAGES_BY_GROUP_ID =
"CREATE INDEX IF NOT EXISTS messagesByGroupId"
+ " ON messages (groupId)";
private static final String FOREIGN_INDEX_MESSAGE_METADATA_BY_MESSAGE_ID =
"CREATE INDEX IF NOT EXISTS messageMetadataByMessageId"
+ " ON messageMetadata (messageId)";
private static final String FOREIGN_INDEX_MESSAGE_METADATA_BY_GROUP_ID =
"CREATE INDEX IF NOT EXISTS messageMetadataByGroupId"
+ " ON messageMetadata (groupId)";
private static final String FOREIGN_INDEX_MESSAGE_DEPENDENCIES_BY_GROUP_ID =
"CREATE INDEX IF NOT EXISTS messageDependenciesByGroupId"
+ " ON messageDependencies (groupId)";
private static final String
FOREIGN_INDEX_MESSAGE_DEPENDENCIES_BY_MESSAGE_ID =
"CREATE INDEX IF NOT EXISTS messageDependenciesByMessageId"
+ " ON messageDependencies (messageId)";
private static final String FOREIGN_INDEX_OFFERS_BY_CONTACT_ID =
"CREATE INDEX IF NOT EXISTS offersByContactId"
+ " ON offers (contactId)";
private static final String FOREIGN_INDEX_STATUSES_BY_MESSAGE_ID =
"CREATE INDEX IF NOT EXISTS statusesByMessageId"
+ " ON statuses (messageId)";
private static final String FOREIGN_INDEX_STATUSES_BY_CONTACT_ID =
"CREATE INDEX IF NOT EXISTS statusesByContactId"
+ " ON statuses (contactId)";
private static final String FOREIGN_INDEX_STATUSES_BY_GROUP_ID =
"CREATE INDEX IF NOT EXISTS statusesByGroupId"
+ " ON statuses (groupId)";
private static final String FOREIGN_INDEX_OUTGOING_KEYS_BY_TRANSPORT_ID =
"CREATE INDEX IF NOT EXISTS outgoingKeysByTransportId"
+ " ON outgoingKeys (transportId)";
private static final String FOREIGN_INDEX_OUTGOING_KEYS_BY_CONTACT_ID =
"CREATE INDEX IF NOT EXISTS outgoingKeysByContactId"
+ " ON outgoingKeys (contactId)";
private static final String
FOREIGN_INDEX_OUTGOING_KEYS_BY_PENDING_CONTACT_ID =
"CREATE INDEX IF NOT EXISTS outgoingKeysByPendingContactId"
+ " ON outgoingKeys (pendingContactId)";
private static final String FOREIGN_INDEX_INCOMING_KEYS_BY_TRANSPORT_ID =
"CREATE INDEX IF NOT EXISTS incomingKeysByTransportId"
+ " ON incomingKeys (transportId)";
private static final String FOREIGN_INDEX_INCOMING_KEYS_BY_KEY_SET_ID =
"CREATE INDEX IF NOT EXISTS incomingKeysByKeySetId"
+ " ON incomingKeys (keySetId)";
private static final Logger LOG = private static final Logger LOG =
getLogger(JdbcDatabase.class.getName()); getLogger(JdbcDatabase.class.getName());
@@ -393,6 +471,7 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
protected void open(String driverClass, boolean reopen, protected void open(String driverClass, boolean reopen,
boolean createForeignKeyIndexes,
@SuppressWarnings("unused") SecretKey key, @SuppressWarnings("unused") SecretKey key,
@Nullable MigrationListener listener) throws DbException { @Nullable MigrationListener listener) throws DbException {
// Load the JDBC driver // Load the JDBC driver
@@ -419,7 +498,7 @@ abstract class JdbcDatabase implements Database<Connection> {
if (LOG.isLoggable(INFO)) { if (LOG.isLoggable(INFO)) {
LOG.info("db dirty? " + wasDirtyOnInitialisation); LOG.info("db dirty? " + wasDirtyOnInitialisation);
} }
createIndexes(txn); createIndexes(txn, createForeignKeyIndexes);
setDirty(txn, true); setDirty(txn, true);
commitTransaction(txn); commitTransaction(txn);
} catch (DbException e) { } catch (DbException e) {
@@ -552,7 +631,8 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
private void createIndexes(Connection txn) throws DbException { private void createIndexes(Connection txn, boolean createForeignKeyIndexes)
throws DbException {
Statement s = null; Statement s = null;
try { try {
s = txn.createStatement(); s = txn.createStatement();
@@ -564,6 +644,31 @@ abstract class JdbcDatabase implements Database<Connection> {
s.executeUpdate(INDEX_STATUSES_BY_CONTACT_ID_TIMESTAMP); s.executeUpdate(INDEX_STATUSES_BY_CONTACT_ID_TIMESTAMP);
s.executeUpdate(INDEX_STATUSES_BY_CONTACT_ID_TX_COUNT_TIMESTAMP); s.executeUpdate(INDEX_STATUSES_BY_CONTACT_ID_TX_COUNT_TIMESTAMP);
s.executeUpdate(INDEX_MESSAGES_BY_CLEANUP_DEADLINE); s.executeUpdate(INDEX_MESSAGES_BY_CLEANUP_DEADLINE);
s.executeUpdate(INDEX_OUTGOING_KEYS_BY_TRANSPORT_ID_KEY_SET_ID);
// Some DB implementations automatically create indexes on columns
// that are foreign keys, others don't
if (createForeignKeyIndexes) {
s.executeUpdate(FOREIGN_INDEX_CONTACTS_BY_LOCAL_AUTHOR_ID);
s.executeUpdate(FOREIGN_INDEX_GROUP_METADATA_BY_GROUP_ID);
s.executeUpdate(FOREIGN_INDEX_GROUP_VISIBILITIES_BY_CONTACT_ID);
s.executeUpdate(FOREIGN_INDEX_GROUP_VISIBILITIES_BY_GROUP_ID);
s.executeUpdate(FOREIGN_INDEX_MESSAGES_BY_GROUP_ID);
s.executeUpdate(FOREIGN_INDEX_MESSAGE_METADATA_BY_MESSAGE_ID);
s.executeUpdate(FOREIGN_INDEX_MESSAGE_METADATA_BY_GROUP_ID);
s.executeUpdate(FOREIGN_INDEX_MESSAGE_DEPENDENCIES_BY_GROUP_ID);
s.executeUpdate(
FOREIGN_INDEX_MESSAGE_DEPENDENCIES_BY_MESSAGE_ID);
s.executeUpdate(FOREIGN_INDEX_OFFERS_BY_CONTACT_ID);
s.executeUpdate(FOREIGN_INDEX_STATUSES_BY_MESSAGE_ID);
s.executeUpdate(FOREIGN_INDEX_STATUSES_BY_CONTACT_ID);
s.executeUpdate(FOREIGN_INDEX_STATUSES_BY_GROUP_ID);
s.executeUpdate(FOREIGN_INDEX_OUTGOING_KEYS_BY_TRANSPORT_ID);
s.executeUpdate(FOREIGN_INDEX_OUTGOING_KEYS_BY_CONTACT_ID);
s.executeUpdate(
FOREIGN_INDEX_OUTGOING_KEYS_BY_PENDING_CONTACT_ID);
s.executeUpdate(FOREIGN_INDEX_INCOMING_KEYS_BY_TRANSPORT_ID);
s.executeUpdate(FOREIGN_INDEX_INCOMING_KEYS_BY_KEY_SET_ID);
}
s.close(); s.close();
} catch (SQLException e) { } catch (SQLException e) {
tryToClose(s, LOG, WARNING); tryToClose(s, LOG, WARNING);
@@ -1914,6 +2019,38 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
@Override
public Collection<String> explainGetMessageIds(Connection txn, GroupId g)
throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = dbTypes.replaceTypes("_EXPLAIN SELECT messageId"
+ " FROM messages"
+ " WHERE groupId = ? AND state = ?");
ps = txn.prepareStatement(sql);
ps.setBytes(1, g.getBytes());
ps.setInt(2, DELIVERED.getValue());
rs = ps.executeQuery();
int cols = rs.getMetaData().getColumnCount();
List<String> explanation = new ArrayList<>();
while (rs.next()) {
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= cols; i++) {
sb.append(rs.getString(i)).append(' ');
}
explanation.add(sb.toString());
}
rs.close();
ps.close();
return explanation;
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@Override @Override
public Collection<MessageId> getMessageIds(Connection txn, GroupId g, public Collection<MessageId> getMessageIds(Connection txn, GroupId g,
Metadata query) throws DbException { Metadata query) throws DbException {
@@ -2597,6 +2734,9 @@ abstract class JdbcDatabase implements Database<Connection> {
PublicKey publicKey = new AgreementPublicKey(rs.getBytes(1)); PublicKey publicKey = new AgreementPublicKey(rs.getBytes(1));
String alias = rs.getString(2); String alias = rs.getString(2);
long timestamp = rs.getLong(3); long timestamp = rs.getLong(3);
if (rs.next()) throw new DbStateException();
rs.close();
ps.close();
return new PendingContact(p, publicKey, alias, timestamp); return new PendingContact(p, publicKey, alias, timestamp);
} catch (SQLException e) { } catch (SQLException e) {
tryToClose(rs, LOG, WARNING); tryToClose(rs, LOG, WARNING);

View File

@@ -0,0 +1,117 @@
package org.briarproject.bramble.db;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.db.DbClosedException;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.MigrationListener;
import org.briarproject.bramble.api.sync.MessageFactory;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.nullsafety.NotNullByDefault;
import org.sqlite.mc.SQLiteMCSqlCipherConfig;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.inject.Inject;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.db.JdbcUtils.tryToClose;
import static org.briarproject.bramble.util.IoUtils.isNonEmptyDirectory;
/**
* Contains all the SQLite-specific code for the database.
*/
@NotNullByDefault
class SqliteDatabase extends JdbcDatabase {
private static final Logger LOG = getLogger(SqliteDatabase.class.getName());
private static final String HASH_TYPE = "BLOB";
private static final String SECRET_TYPE = "BLOB";
private static final String BINARY_TYPE = "BLOB";
private static final String COUNTER_TYPE =
"INTEGER PRIMARY KEY AUTOINCREMENT";
private static final String STRING_TYPE = "VARCHAR";
private static final String EXPLAIN_COMMAND = "EXPLAIN QUERY PLAN";
private static final DatabaseTypes dbTypes = new DatabaseTypes(HASH_TYPE,
SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE,
EXPLAIN_COMMAND);
private final DatabaseConfig config;
private final String url;
@Nullable
private volatile Properties properties = null;
@Inject
SqliteDatabase(DatabaseConfig config, MessageFactory messageFactory,
Clock clock) {
super(dbTypes, messageFactory, clock);
this.config = config;
File dir = config.getDatabaseDirectory();
String path = new File(dir, "db").getAbsolutePath();
url = "jdbc:sqlite:" + path + "?cipher=sqlcipher";
}
@Override
public boolean open(SecretKey key, @Nullable MigrationListener listener)
throws DbException {
properties = SQLiteMCSqlCipherConfig.getDefault()
.withHexKey(key.getBytes())
.build()
.toProperties();
File dir = config.getDatabaseDirectory();
boolean reopen = isNonEmptyDirectory(dir);
if (LOG.isLoggable(INFO)) LOG.info("Reopening DB: " + reopen);
if (!reopen && dir.mkdirs()) LOG.info("Created database directory");
super.open("org.sqlite.JDBC", reopen, true, key, listener);
return reopen;
}
@Override
public void close() throws DbException {
Connection c = null;
try {
c = createConnection();
setDirty(c, false);
c.close();
closeAllConnections();
} catch (SQLException e) {
tryToClose(c, LOG, WARNING);
throw new DbException(e);
}
}
@Override
protected Connection createConnection() throws DbException, SQLException {
Properties properties = this.properties;
if (properties == null) throw new DbClosedException();
Connection c = DriverManager.getConnection(url, properties);
Statement s = null;
try {
s = c.createStatement();
s.execute("PRAGMA foreign_keys = ON");
s.execute("PRAGMA secure_delete = ON");
s.close();
} catch (SQLException e) {
tryToClose(s, LOG, WARNING);
tryToClose(c, LOG, WARNING);
throw new DbException(e);
}
return c;
}
@Override
protected void compactAndClose() throws DbException {
close();
}
}

View File

@@ -388,6 +388,7 @@ abstract class AbstractBluetoothPlugin<S, SS> implements BluetoothPlugin,
} }
// Validate the UUID // Validate the UUID
try { try {
//noinspection ResultOfMethodCallIgnored
UUID.fromString(uuid); UUID.fromString(uuid);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
if (LOG.isLoggable(WARNING)) LOG.warning("Invalid UUID " + uuid); if (LOG.isLoggable(WARNING)) LOG.warning("Invalid UUID " + uuid);

View File

@@ -75,6 +75,7 @@ import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_ONLY_WHE
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_PORT; import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_PORT;
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION_V3; import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION_V3;
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_BATTERY; import static org.briarproject.bramble.api.plugin.TorConstants.REASON_BATTERY;
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_COUNTRY_BLOCKED;
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_MOBILE_DATA; import static org.briarproject.bramble.api.plugin.TorConstants.REASON_MOBILE_DATA;
import static org.briarproject.bramble.plugin.tor.TorRendezvousCrypto.SEED_BYTES; import static org.briarproject.bramble.plugin.tor.TorRendezvousCrypto.SEED_BYTES;
import static org.briarproject.bramble.util.IoUtils.tryToClose; import static org.briarproject.bramble.util.IoUtils.tryToClose;
@@ -105,6 +106,7 @@ class TorPlugin implements DuplexPlugin, EventListener {
private final PluginCallback callback; private final PluginCallback callback;
private final long maxLatency; private final long maxLatency;
private final int maxIdleTime; private final int maxIdleTime;
private final boolean canVerifyLetsEncryptCerts;
private final int socketTimeout; private final int socketTimeout;
private final AtomicBoolean used = new AtomicBoolean(false); private final AtomicBoolean used = new AtomicBoolean(false);
@@ -124,7 +126,8 @@ class TorPlugin implements DuplexPlugin, EventListener {
TorWrapper tor, TorWrapper tor,
PluginCallback callback, PluginCallback callback,
long maxLatency, long maxLatency,
int maxIdleTime) { int maxIdleTime,
boolean canVerifyLetsEncryptCerts) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.wakefulIoExecutor = wakefulIoExecutor; this.wakefulIoExecutor = wakefulIoExecutor;
this.networkManager = networkManager; this.networkManager = networkManager;
@@ -138,6 +141,7 @@ class TorPlugin implements DuplexPlugin, EventListener {
this.callback = callback; this.callback = callback;
this.maxLatency = maxLatency; this.maxLatency = maxLatency;
this.maxIdleTime = maxIdleTime; this.maxIdleTime = maxIdleTime;
this.canVerifyLetsEncryptCerts = canVerifyLetsEncryptCerts;
if (maxIdleTime > Integer.MAX_VALUE / 2) { if (maxIdleTime > Integer.MAX_VALUE / 2) {
socketTimeout = Integer.MAX_VALUE; socketTimeout = Integer.MAX_VALUE;
} else { } else {
@@ -293,7 +297,7 @@ class TorPlugin implements DuplexPlugin, EventListener {
List<String> bridges = new ArrayList<>(); List<String> bridges = new ArrayList<>();
for (BridgeType bridgeType : bridgeTypes) { for (BridgeType bridgeType : bridgeTypes) {
bridges.addAll(circumventionProvider.getBridges(bridgeType, bridges.addAll(circumventionProvider.getBridges(bridgeType,
countryCode)); countryCode, canVerifyLetsEncryptCerts));
} }
tor.enableBridges(bridges); tor.enableBridges(bridges);
} }
@@ -487,8 +491,8 @@ class TorPlugin implements DuplexPlugin, EventListener {
boolean wifi = status.isWifi(); boolean wifi = status.isWifi();
boolean ipv6Only = status.isIpv6Only(); boolean ipv6Only = status.isIpv6Only();
String country = locationUtils.getCurrentCountry(); String country = locationUtils.getCurrentCountry();
boolean bridgesByDefault = boolean blocked =
circumventionProvider.shouldUseBridges(country); circumventionProvider.isTorProbablyBlocked(country);
boolean enabledByUser = settings.getBoolean(PREF_PLUGIN_ENABLE, boolean enabledByUser = settings.getBoolean(PREF_PLUGIN_ENABLE,
DEFAULT_PREF_PLUGIN_ENABLE); DEFAULT_PREF_PLUGIN_ENABLE);
int network = settings.getInt(PREF_TOR_NETWORK, int network = settings.getInt(PREF_TOR_NETWORK,
@@ -498,6 +502,7 @@ class TorPlugin implements DuplexPlugin, EventListener {
boolean onlyWhenCharging = boolean onlyWhenCharging =
settings.getBoolean(PREF_TOR_ONLY_WHEN_CHARGING, settings.getBoolean(PREF_TOR_ONLY_WHEN_CHARGING,
DEFAULT_PREF_TOR_ONLY_WHEN_CHARGING); DEFAULT_PREF_TOR_ONLY_WHEN_CHARGING);
boolean bridgesWork = circumventionProvider.doBridgesWork(country);
boolean automatic = network == PREF_TOR_NETWORK_AUTOMATIC; boolean automatic = network == PREF_TOR_NETWORK_AUTOMATIC;
if (LOG.isLoggable(INFO)) { if (LOG.isLoggable(INFO)) {
@@ -527,6 +532,10 @@ class TorPlugin implements DuplexPlugin, EventListener {
LOG.info("Configured not to use mobile data"); LOG.info("Configured not to use mobile data");
reasonsDisabled |= REASON_MOBILE_DATA; reasonsDisabled |= REASON_MOBILE_DATA;
} }
if (automatic && blocked && !bridgesWork) {
LOG.info("Country is blocked");
reasonsDisabled |= REASON_COUNTRY_BLOCKED;
}
if (reasonsDisabled != 0) { if (reasonsDisabled != 0) {
LOG.info("Disabling network due to settings"); LOG.info("Disabling network due to settings");
@@ -534,7 +543,7 @@ class TorPlugin implements DuplexPlugin, EventListener {
LOG.info("Enabling network"); LOG.info("Enabling network");
enableNetwork = true; enableNetwork = true;
if (network == PREF_TOR_NETWORK_WITH_BRIDGES || if (network == PREF_TOR_NETWORK_WITH_BRIDGES ||
(automatic && bridgesByDefault)) { (automatic && bridgesWork)) {
if (ipv6Only) { if (ipv6Only) {
bridgeTypes = asList(MEEK, SNOWFLAKE); bridgeTypes = asList(MEEK, SNOWFLAKE);
} else { } else {

View File

@@ -1,7 +1,6 @@
package org.briarproject.bramble.contact; package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.UnsupportedVersionException;
import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.contact.HandshakeManager.HandshakeResult; import org.briarproject.bramble.api.contact.HandshakeManager.HandshakeResult;
import org.briarproject.bramble.api.contact.PendingContact; import org.briarproject.bramble.api.contact.PendingContact;
@@ -28,7 +27,6 @@ import org.junit.Test;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Arrays; import java.util.Arrays;
@@ -125,12 +123,12 @@ public class HandshakeManagerImplTest extends BrambleMockTestCase {
assertEquals(alice, result.isAlice()); assertEquals(alice, result.isAlice());
} }
@Test(expected = UnsupportedVersionException.class) @Test
public void testHandshakeAsAliceWithPeerVersion_0_0() throws Exception { public void testHandshakeAsAliceWithPeerVersion_0_0() throws Exception {
testHandshakeWithPeerVersion_0_0(true); testHandshakeWithPeerVersion_0_0(true);
} }
@Test(expected = UnsupportedVersionException.class) @Test
public void testHandshakeAsBobWithPeerVersion_0_0() throws Exception { public void testHandshakeAsBobWithPeerVersion_0_0() throws Exception {
testHandshakeWithPeerVersion_0_0(false); testHandshakeWithPeerVersion_0_0(false);
} }
@@ -142,8 +140,20 @@ public class HandshakeManagerImplTest extends BrambleMockTestCase {
expectSendKey(); expectSendKey();
// Remote peer does not send minor version, so use old key derivation // Remote peer does not send minor version, so use old key derivation
expectReceiveKey(); expectReceiveKey();
expectDeriveMasterKey_0_0(alice);
expectDeriveProof(alice);
expectSendProof();
expectReceiveProof();
expectSendEof();
expectReceiveEof();
expectVerifyOwnership(alice, true);
handshakeManager.handshake(pendingContact.getId(), in, streamWriter); HandshakeResult result = handshakeManager.handshake(
pendingContact.getId(), in, streamWriter);
assertArrayEquals(masterKey.getBytes(),
result.getMasterKey().getBytes());
assertEquals(alice, result.isAlice());
} }
@Test(expected = FormatException.class) @Test(expected = FormatException.class)
@@ -231,6 +241,15 @@ public class HandshakeManagerImplTest extends BrambleMockTestCase {
}}); }});
} }
private void expectDeriveMasterKey_0_0(boolean alice) throws Exception {
context.checking(new Expectations() {{
oneOf(handshakeCrypto).deriveMasterKey_0_0(theirStaticPublicKey,
theirEphemeralPublicKey, ourStaticKeyPair,
ourEphemeralKeyPair, alice);
will(returnValue(masterKey));
}});
}
private void expectDeriveProof(boolean alice) { private void expectDeriveProof(boolean alice) {
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(handshakeCrypto).proveOwnership(masterKey, alice); oneOf(handshakeCrypto).proveOwnership(masterKey, alice);

View File

@@ -60,6 +60,22 @@ public class KeyAgreementTest extends BrambleTestCase {
assertArrayEquals(aShared.getBytes(), bShared.getBytes()); assertArrayEquals(aShared.getBytes(), bShared.getBytes());
} }
@Test
public void testDerivesStaticEphemeralSharedSecretBadly() throws Exception {
String label = getRandomString(123);
KeyPair aStatic = crypto.generateAgreementKeyPair();
KeyPair aEphemeral = crypto.generateAgreementKeyPair();
KeyPair bStatic = crypto.generateAgreementKeyPair();
KeyPair bEphemeral = crypto.generateAgreementKeyPair();
SecretKey aShared = crypto.deriveSharedSecretBadly(label,
bStatic.getPublic(), bEphemeral.getPublic(), aStatic,
aEphemeral, true, inputs);
SecretKey bShared = crypto.deriveSharedSecretBadly(label,
aStatic.getPublic(), aEphemeral.getPublic(), bStatic,
bEphemeral, false, inputs);
assertArrayEquals(aShared.getBytes(), bShared.getBytes());
}
@Test @Test
public void testDerivesStaticEphemeralSharedSecret() throws Exception { public void testDerivesStaticEphemeralSharedSecret() throws Exception {
String label = getRandomString(123); String label = getRandomString(123);

View File

@@ -1,45 +0,0 @@
package org.briarproject.bramble.crypto;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.SecureRandomSpi;
import static java.util.Arrays.fill;
/**
* A fake SecureRandom implementation for testing, which returns all zeroes.
*/
public class NeitherSecureNorRandom extends SecureRandom {
private static final Provider PROVIDER =
new NeitherSecureNorRandomProvider();
public NeitherSecureNorRandom() {
super(new NeitherSecureNorRandomSpi(), PROVIDER);
}
private static class NeitherSecureNorRandomSpi extends SecureRandomSpi {
@Override
protected byte[] engineGenerateSeed(int length) {
return new byte[length];
}
@Override
protected void engineNextBytes(byte[] b) {
fill(b, (byte) 0);
}
@Override
protected void engineSetSeed(byte[] seed) {
// Thank you for your input
}
}
private static class NeitherSecureNorRandomProvider extends Provider {
private NeitherSecureNorRandomProvider() {
super("NeitherSecureNorRandom", 1.0, "Only for testing");
}
}
}

View File

@@ -0,0 +1,34 @@
package org.briarproject.bramble.crypto;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.Blake2bDigest;
import org.bouncycastle.crypto.engines.Salsa20Engine;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.NotThreadSafe;
@NotThreadSafe
@NotNullByDefault
class PseudoRandom {
private final Salsa20Engine cipher = new Salsa20Engine();
PseudoRandom(byte[] seed) {
// Hash the seed to produce a 32-byte key
byte[] key = new byte[32];
Digest digest = new Blake2bDigest(256);
digest.update(seed, 0, seed.length);
digest.doFinal(key, 0);
// Initialise the stream cipher with an all-zero nonce
byte[] nonce = new byte[8];
cipher.init(true, new ParametersWithIV(new KeyParameter(key), nonce));
}
byte[] nextBytes(int length) {
byte[] in = new byte[length], out = new byte[length];
cipher.processBytes(in, 0, length, out, 0);
return out;
}
}

View File

@@ -0,0 +1,46 @@
package org.briarproject.bramble.crypto;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.SecureRandomSpi;
class PseudoSecureRandom extends SecureRandom {
private static final Provider PROVIDER = new PseudoSecureRandomProvider();
PseudoSecureRandom(byte[] seed) {
super(new PseudoSecureRandomSpi(seed), PROVIDER);
}
private static class PseudoSecureRandomSpi extends SecureRandomSpi {
private final PseudoRandom pseudoRandom;
private PseudoSecureRandomSpi(byte[] seed) {
pseudoRandom = new PseudoRandom(seed);
}
@Override
protected byte[] engineGenerateSeed(int length) {
return pseudoRandom.nextBytes(length);
}
@Override
protected void engineNextBytes(byte[] b) {
byte[] random = pseudoRandom.nextBytes(b.length);
System.arraycopy(random, 0, b, 0, b.length);
}
@Override
protected void engineSetSeed(byte[] seed) {
// Thank you for your input
}
}
private static class PseudoSecureRandomProvider extends Provider {
private PseudoSecureRandomProvider() {
super("PseudoSecureRandom", 1.0, "Only for testing");
}
}
}

View File

@@ -0,0 +1,37 @@
package org.briarproject.bramble.db;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.sync.MessageFactory;
import org.briarproject.bramble.api.system.Clock;
import org.junit.BeforeClass;
import java.sql.Connection;
import static org.briarproject.bramble.test.TestUtils.isOptionalTestEnabled;
import static org.junit.Assume.assumeTrue;
public class H2SqliteDatabasePerformanceComparisonTest
extends DatabasePerformanceComparisonTest {
@BeforeClass
public static void setUpClass() {
assumeTrue(isOptionalTestEnabled(
H2SqliteDatabasePerformanceComparisonTest.class));
}
@Override
Database<Connection> createDatabase(boolean conditionA,
DatabaseConfig databaseConfig, MessageFactory messageFactory,
Clock clock) {
if (conditionA) {
return new H2Database(databaseConfig, messageFactory, clock);
} else {
return new SqliteDatabase(databaseConfig, messageFactory, clock);
}
}
@Override
protected String getTestName() {
return getClass().getSimpleName();
}
}

View File

@@ -10,14 +10,21 @@ import static org.junit.Assume.assumeTrue;
public class HyperSqlDatabaseTest extends JdbcDatabaseTest { public class HyperSqlDatabaseTest extends JdbcDatabaseTest {
@Override
@Before @Before
public void setUp() { public void setUp() {
assumeTrue(isCryptoStrengthUnlimited()); assumeTrue(isCryptoStrengthUnlimited());
super.setUp();
} }
@Override @Override
protected JdbcDatabase createDatabase(DatabaseConfig config, protected JdbcDatabase createDatabase(DatabaseConfig config,
MessageFactory messageFactory, Clock clock) { MessageFactory messageFactory, Clock clock) {
return new HyperSqlDatabase(config, messageFactory ,clock); return new HyperSqlDatabase(config, messageFactory, clock);
}
@Override
public void testExplainGetMessageIds() {
// Ugh, HSQLDB can't handle EXPLAIN PLAN FOR in prepared statements
} }
} }

View File

@@ -2500,6 +2500,21 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertEquals(NO_CLEANUP_DEADLINE, db.getNextCleanupDeadline(txn)); assertEquals(NO_CLEANUP_DEADLINE, db.getNextCleanupDeadline(txn));
} }
// FIXME: Remove
@Test
public void testExplainGetMessageIds() throws Exception {
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
db.addGroup(txn, group);
Collection<String> explanation = db.explainGetMessageIds(txn, groupId);
db.commitTransaction(txn);
db.close();
System.out.println("getMessageIds(T, GroupId)");
for (String line : explanation) System.out.println(line);
System.out.println();
}
private Database<Connection> open(boolean resume) throws Exception { private Database<Connection> open(boolean resume) throws Exception {
return open(resume, new TestMessageFactory(), new SystemClock()); return open(resume, new TestMessageFactory(), new SystemClock());
} }

View File

@@ -0,0 +1,25 @@
package org.briarproject.bramble.db;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.sync.MessageFactory;
import org.briarproject.bramble.api.system.Clock;
import org.junit.Before;
import static org.briarproject.bramble.test.TestUtils.isCryptoStrengthUnlimited;
import static org.junit.Assume.assumeTrue;
public class SqliteDatabaseTest extends JdbcDatabaseTest {
@Override
@Before
public void setUp() {
assumeTrue(isCryptoStrengthUnlimited());
super.setUp();
}
@Override
protected JdbcDatabase createDatabase(DatabaseConfig config,
MessageFactory messageFactory, Clock clock) {
return new SqliteDatabase(config, messageFactory, clock);
}
}

View File

@@ -15,10 +15,9 @@ import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.CaptureArgumentAction; import org.briarproject.bramble.test.CaptureArgumentAction;
import org.briarproject.bramble.test.PredicateMatcher; import org.briarproject.bramble.test.PredicateMatcher;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.imposters.ByteBuddyClassImposteriser;
import org.junit.Test; import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@@ -52,12 +51,17 @@ public class KeyAgreementTransportTest extends BrambleMockTestCase {
private final KeyAgreementConnection keyAgreementConnection = private final KeyAgreementConnection keyAgreementConnection =
new KeyAgreementConnection(duplexTransportConnection, transportId); new KeyAgreementConnection(duplexTransportConnection, transportId);
private final InputStream inputStream = private final InputStream inputStream;
new ByteArrayInputStream(new byte[0]); private final OutputStream outputStream;
private final OutputStream outputStream = new ByteArrayOutputStream();
private KeyAgreementTransport kat; private KeyAgreementTransport kat;
public KeyAgreementTransportTest() {
context.setImposteriser(ByteBuddyClassImposteriser.INSTANCE);
inputStream = context.mock(InputStream.class);
outputStream = context.mock(OutputStream.class);
}
@Test @Test
public void testSendKey() throws Exception { public void testSendKey() throws Exception {
byte[] key = getRandomBytes(123); byte[] key = getRandomBytes(123);

View File

@@ -21,11 +21,11 @@ import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.properties.TransportPropertyManager; import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.TaskScheduler; import org.briarproject.bramble.api.system.TaskScheduler;
import org.briarproject.bramble.crypto.NeitherSecureNorRandom;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.ImmediateExecutor; import org.briarproject.bramble.test.ImmediateExecutor;
import org.briarproject.bramble.test.RunAction; import org.briarproject.bramble.test.RunAction;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.imposters.ByteBuddyClassImposteriser;
import org.junit.Test; import org.junit.Test;
import java.security.SecureRandom; import java.security.SecureRandom;
@@ -55,6 +55,7 @@ public class PollerImplTest extends BrambleMockTestCase {
context.mock(TransportPropertyManager.class); context.mock(TransportPropertyManager.class);
private final Clock clock = context.mock(Clock.class); private final Clock clock = context.mock(Clock.class);
private final Cancellable cancellable = context.mock(Cancellable.class); private final Cancellable cancellable = context.mock(Cancellable.class);
private final SecureRandom random;
private final Executor ioExecutor = new ImmediateExecutor(); private final Executor ioExecutor = new ImmediateExecutor();
private final TransportId transportId = getTransportId(); private final TransportId transportId = getTransportId();
@@ -66,8 +67,8 @@ public class PollerImplTest extends BrambleMockTestCase {
private final PollerImpl poller; private final PollerImpl poller;
public PollerImplTest() { public PollerImplTest() {
// Use a fake SecureRandom that returns all zeroes context.setImposteriser(ByteBuddyClassImposteriser.INSTANCE);
SecureRandom random = new NeitherSecureNorRandom(); random = context.mock(SecureRandom.class);
Executor wakefulIoExecutor = new ImmediateExecutor(); Executor wakefulIoExecutor = new ImmediateExecutor();
poller = new PollerImpl(ioExecutor, wakefulIoExecutor, scheduler, poller = new PollerImpl(ioExecutor, wakefulIoExecutor, scheduler,
connectionManager, connectionRegistry, pluginManager, connectionManager, connectionRegistry, pluginManager,
@@ -351,10 +352,12 @@ public class PollerImplTest extends BrambleMockTestCase {
// Running the polling task schedules the next polling task // Running the polling task schedules the next polling task
oneOf(plugin).getPollingInterval(); oneOf(plugin).getPollingInterval();
will(returnValue(pollingInterval)); will(returnValue(pollingInterval));
oneOf(random).nextDouble();
will(returnValue(0.5));
oneOf(clock).currentTimeMillis(); oneOf(clock).currentTimeMillis();
will(returnValue(now)); will(returnValue(now));
oneOf(scheduler).schedule(with(any(Runnable.class)), oneOf(scheduler).schedule(with(any(Runnable.class)),
with(ioExecutor), with(0L), with(ioExecutor), with((long) (pollingInterval * 0.5)),
with(MILLISECONDS)); with(MILLISECONDS));
will(returnValue(cancellable)); will(returnValue(cancellable));
// Get the transport properties and connected contacts // Get the transport properties and connected contacts
@@ -393,10 +396,12 @@ public class PollerImplTest extends BrambleMockTestCase {
// Running the polling task schedules the next polling task // Running the polling task schedules the next polling task
oneOf(plugin).getPollingInterval(); oneOf(plugin).getPollingInterval();
will(returnValue(pollingInterval)); will(returnValue(pollingInterval));
oneOf(random).nextDouble();
will(returnValue(0.5));
oneOf(clock).currentTimeMillis(); oneOf(clock).currentTimeMillis();
will(returnValue(now)); will(returnValue(now));
oneOf(scheduler).schedule(with(any(Runnable.class)), oneOf(scheduler).schedule(with(any(Runnable.class)),
with(ioExecutor), with(0L), with(ioExecutor), with((long) (pollingInterval * 0.5)),
with(MILLISECONDS)); with(MILLISECONDS));
will(returnValue(cancellable)); will(returnValue(cancellable));
// Get the transport properties and connected contacts // Get the transport properties and connected contacts

View File

@@ -6,22 +6,25 @@ dependencyVerification {
'com.fasterxml.jackson.core:jackson-databind:2.13.4:jackson-databind-2.13.4.jar:c9faff420d9e2c7e1e4711dbeebec2506a32c9942027211c5c293d8d87807eb6', 'com.fasterxml.jackson.core:jackson-databind:2.13.4:jackson-databind-2.13.4.jar:c9faff420d9e2c7e1e4711dbeebec2506a32c9942027211c5c293d8d87807eb6',
'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79', 'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7', 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger-compiler:2.51.1:dagger-compiler-2.51.1.jar:14cf2def1c4c8cd3b977840e297b463191d537cd1c8330992ca5c0b341a641ad', 'com.google.dagger:dagger-compiler:2.45:dagger-compiler-2.45.jar:5617dfb994537dba5b41f3744a6dd13ec3cd99789c065e0d5c6fa9f21cf7ca25',
'com.google.dagger:dagger-spi:2.51.1:dagger-spi-2.51.1.jar:deb52030b92b27c5dcd76b2c0747f1cf105b60939f6073b43eb06cfe7c9ba601', 'com.google.dagger:dagger-producers:2.45:dagger-producers-2.45.jar:a05abb4c3ccf6bb0f056bdcb5ef973898ecf172952ab5948a824aeea6c86ecaa',
'com.google.dagger:dagger:2.51.1:dagger-2.51.1.jar:c3891a4c4a4e48682888ca321eaf8497004b286e1d9a2936867373219f7dd86d', 'com.google.dagger:dagger-spi:2.45:dagger-spi-2.45.jar:7cd6f0b09d88e64a9c97bc80e544ab8ac8fdee9301754413585a74cf64222b27',
'com.google.devtools.ksp:symbol-processing-api:1.9.20-1.0.14:symbol-processing-api-1.9.20-1.0.14.jar:d0339396f40dc9eb3b3f7bc86257f93869ee23448fa31ec4a1de900c6b7ae6d7', 'com.google.dagger:dagger:2.45:dagger-2.45.jar:f011cae7d2c0fb7ea17c34e05bc10e768b1081a5892ad019cf1fdb0e125c49c1',
'com.google.errorprone:error_prone_annotations:2.23.0:error_prone_annotations-2.23.0.jar:ec6f39f068b6ff9ac323c68e28b9299f8c0a80ca512dccb1d4a70f40ac3ec054', 'com.google.devtools.ksp:symbol-processing-api:1.7.0-1.0.6:symbol-processing-api-1.7.0-1.0.6.jar:adc29417be5ca9ff42118105fea4e36d9ef44987abfc41432309371a60198941',
'com.google.errorprone:error_prone_annotations:2.7.1:error_prone_annotations-2.7.1.jar:cd5257c08a246cf8628817ae71cb822be192ef91f6881ca4a3fcff4f1de1cff3',
'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30', 'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30',
'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e', 'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e',
'com.google.guava:failureaccess:1.0.2:failureaccess-1.0.2.jar:8a8f81cf9b359e3f6dfa691a1e776985c061ef2f223c9b2c80753e1b458e8064', 'com.google.guava:failureaccess:1.0.1:failureaccess-1.0.1.jar:a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26',
'com.google.guava:guava:33.0.0-jre:guava-33.0.0-jre.jar:f4d85c3e4d411694337cb873abea09b242b664bb013320be6105327c45991537', 'com.google.guava:guava:31.0.1-jre:guava-31.0.1-jre.jar:d5be94d65e87bd219fb3193ad1517baa55a3b88fc91d21cf735826ab5af087b9',
'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99', 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
'com.google.j2objc:j2objc-annotations:1.3:j2objc-annotations-1.3.jar:21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b',
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c', 'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
'com.squareup.okhttp3:mockwebserver:4.10.0:mockwebserver-4.10.0.jar:af29da234e63159d6e0dea43bf8288eea97d71cdf1651a5ee2d6c0d0d4adbf8f', 'com.squareup.okhttp3:mockwebserver:4.10.0:mockwebserver-4.10.0.jar:af29da234e63159d6e0dea43bf8288eea97d71cdf1651a5ee2d6c0d0d4adbf8f',
'com.squareup.okhttp3:okhttp:4.12.0:okhttp-4.12.0.jar:b1050081b14bb7a3a7e55a4d3ef01b5dcfabc453b4573a4fc019767191d5f4e0', 'com.squareup.okhttp3:okhttp:4.10.0:okhttp-4.10.0.jar:7580f14fa1691206e37081ad3f92063b1603b328da0bb316f2fef02e0562e7ec',
'com.squareup.okio:okio-jvm:3.6.0:okio-jvm-3.6.0.jar:67543f0736fc422ae927ed0e504b98bc5e269fda0d3500579337cb713da28412', 'com.squareup.okio:okio-jvm:3.0.0:okio-jvm-3.0.0.jar:be64a0cc1f28ea9cd5c970dd7e7557af72c808d738c495b397bf897c9921e907',
'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291', 'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
'com.squareup:kotlinpoet:1.11.0:kotlinpoet-1.11.0.jar:2887ada1ca03dd83baa2758640d87e840d1907564db0ef88d2289c868a980492', 'com.squareup:kotlinpoet:1.11.0:kotlinpoet-1.11.0.jar:2887ada1ca03dd83baa2758640d87e840d1907564db0ef88d2289c868a980492',
'io.github.willena:sqlite-jdbc:3.41.2.1:sqlite-jdbc-3.41.2.1.jar:fb60e7137c1791db89240701338d31ca42a0bec5508c1aab1c1131cf885f2309',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3', 'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3',
'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11', 'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11',
@@ -34,10 +37,10 @@ dependencyVerification {
'org.bouncycastle:bcprov-jdk15to18:1.71:bcprov-jdk15to18-1.71.jar:143aaa4a40edd5fc2a18db7900059f6c16f4d931b94b94b20f7e2238e6662886', 'org.bouncycastle:bcprov-jdk15to18:1.71:bcprov-jdk15to18-1.71.jar:143aaa4a40edd5fc2a18db7900059f6c16f4d931b94b94b20f7e2238e6662886',
'org.briarproject:jtorctl:0.5:jtorctl-0.5.jar:43f8c7d390169772b9a2c82ab806c8414c136a2a8636c555e22754bb7260793b', 'org.briarproject:jtorctl:0.5:jtorctl-0.5.jar:43f8c7d390169772b9a2c82ab806c8414c136a2a8636c555e22754bb7260793b',
'org.briarproject:null-safety:0.1:null-safety-0.1.jar:161760de5e838cb982bafa973df820675d4397098e9a91637a36a306d43ba011', 'org.briarproject:null-safety:0.1:null-safety-0.1.jar:161760de5e838cb982bafa973df820675d4397098e9a91637a36a306d43ba011',
'org.briarproject:onionwrapper-core:0.1.3:onionwrapper-core-0.1.3.jar:32d08c9d81a9591e08d7e64e3569334fee21f503b00514006f2e6cbbd409d0df', 'org.briarproject:onionwrapper-core:0.0.5:onionwrapper-core-0.0.5.jar:9071678323535cb3dfe0f3add96066037db43ea024333eba0117c759bcbd8d63',
'org.briarproject:socks-socket:0.1:socks-socket-0.1.jar:e5898822d10f5390363c5dddb945891648c92cf93ba50709e07f0d173ec0eb4b', 'org.briarproject:socks-socket:0.1:socks-socket-0.1.jar:e5898822d10f5390363c5dddb945891648c92cf93ba50709e07f0d173ec0eb4b',
'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a', 'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a',
'org.checkerframework:checker-qual:3.41.0:checker-qual-3.41.0.jar:2f9f245bf68e4259d610894f2406dc1f6363dc639302bd566e8272e4f4541172', 'org.checkerframework:checker-qual:3.12.0:checker-qual-3.12.0.jar:ff10785ac2a357ec5de9c293cb982a2cbb605c0309ea4cc1cb9b9bc6dbe7f3cb',
'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619', 'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.22:animal-sniffer-ant-tasks-1.22.jar:3f6afeb3e09301d2d7179ed1db21e3ad8846c1e38415ad832a395138ae3f4218', 'org.codehaus.mojo:animal-sniffer-ant-tasks:1.22:animal-sniffer-ant-tasks-1.22.jar:3f6afeb3e09301d2d7179ed1db21e3ad8846c1e38415ad832a395138ae3f4218',
'org.codehaus.mojo:animal-sniffer:1.22:animal-sniffer-1.22.jar:f18c11a25bdd8b520b9c6a28cbb6f33007c812ab0051b6be3f0778e660aa501c', 'org.codehaus.mojo:animal-sniffer:1.22:animal-sniffer-1.22.jar:f18c11a25bdd8b520b9c6a28cbb6f33007c812ab0051b6be3f0778e660aa501c',
@@ -46,13 +49,17 @@ dependencyVerification {
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050', 'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
'org.hsqldb:hsqldb:2.3.5:hsqldb-2.3.5.jar:6676a6977ac98997a80f827ddbd3fe8ca1e0853dad1492512135fd1a222ccfad', 'org.hsqldb:hsqldb:2.3.5:hsqldb-2.3.5.jar:6676a6977ac98997a80f827ddbd3fe8ca1e0853dad1492512135fd1a222ccfad',
'org.jetbrains.kotlin:kotlin-reflect:1.6.10:kotlin-reflect-1.6.10.jar:3277ac102ae17aad10a55abec75ff5696c8d109790396434b496e75087854203', 'org.jetbrains.kotlin:kotlin-reflect:1.6.10:kotlin-reflect-1.6.10.jar:3277ac102ae17aad10a55abec75ff5696c8d109790396434b496e75087854203',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.9.10:kotlin-stdlib-common-1.9.10.jar:cde3341ba18a2ba262b0b7cf6c55b20c90e8d434e42c9a13e6a3f770db965a88', 'org.jetbrains.kotlin:kotlin-stdlib-common:1.6.20:kotlin-stdlib-common-1.6.20.jar:8da40a2520d30dcb1012176fe93d24e82d08a3e346c37e0343b0fb6f64f6be01',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0:kotlin-stdlib-jdk7-1.9.0.jar:b7979a7aac94055f0d9f1fd3b47ce5ffe1cb6032a842ba9fbe7186f085289178', 'org.jetbrains.kotlin:kotlin-stdlib-common:1.7.0:kotlin-stdlib-common-1.7.0.jar:59c6ff64fe9a6604afce03e8aaa75f83586c6030ac71fb0b34ee7cdefed3618f',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.10:kotlin-stdlib-jdk7-1.9.10.jar:ac6361bf9ad1ed382c2103d9712c47cdec166232b4903ed596e8876b0681c9b7', 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.5.31:kotlin-stdlib-jdk7-1.5.31.jar:a25bf47353ce899d843cbddee516d621a73473e7fba97f8d0301e7b4aed7c15f',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0:kotlin-stdlib-jdk8-1.9.0.jar:a59fa24fdf1ffb594baecdbf0fd10010f977cea10236d487fe3464977a7377fa', 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.10:kotlin-stdlib-jdk7-1.6.10.jar:2aedcdc6b69b33bdf5cc235bcea88e7cf6601146bb6bcdffdb312bbacd7be261',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.10:kotlin-stdlib-jdk8-1.9.10.jar:a4c74d94d64ce1abe53760fe0389dd941f6fc558d0dab35e47c085a11ec80f28', 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.0:kotlin-stdlib-jdk7-1.7.0.jar:07e91be9b2ca20672d2bdb7e181b766e73453a2da13492b5ddaee8fa47aea239',
'org.jetbrains.kotlin:kotlin-stdlib:1.9.10:kotlin-stdlib-1.9.10.jar:55e989c512b80907799f854309f3bc7782c5b3d13932442d0379d5c472711504', 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.31:kotlin-stdlib-jdk8-1.5.31.jar:b548f7767aacf029d2417e47440742bd6d3ebede19b60386e23554ce5c4c5fdc',
'org.jetbrains.kotlin:kotlin-stdlib:1.9.20:kotlin-stdlib-1.9.20.jar:28a35bcdff46d864f80f346a617e486284b208d17378c41900dfb1de95a90e6c', 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.10:kotlin-stdlib-jdk8-1.6.10.jar:1456d82d039ea30d8485b032901f52bbf07e7cdbe8bb1f8708ad32a8574c41ce',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.0:kotlin-stdlib-jdk8-1.7.0.jar:cf058e11db1dfc9944680c8c61b95ac689aaaa8a3eb30bced028100f038f030b',
'org.jetbrains.kotlin:kotlin-stdlib:1.6.20:kotlin-stdlib-1.6.20.jar:eeb51c2b67b26233fd81d0bc4f8044ec849718890905763ceffd84a31e2cb799',
'org.jetbrains.kotlin:kotlin-stdlib:1.7.0:kotlin-stdlib-1.7.0.jar:aa88e9625577957f3249a46cb6e166ee09b369e600f7a11d148d16b0a6d87f05',
'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.5.0:kotlinx-metadata-jvm-0.5.0.jar:ca063a96639b08b9eaa0de4d65e899480740a6efbe28ab9a8681a2ced03055a4',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478', 'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09', 'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b', 'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',

View File

@@ -19,6 +19,7 @@ import org.briarproject.onionwrapper.CircumventionProvider;
import org.briarproject.onionwrapper.LocationUtils; import org.briarproject.onionwrapper.LocationUtils;
import org.briarproject.onionwrapper.MacTorWrapper; import org.briarproject.onionwrapper.MacTorWrapper;
import org.briarproject.onionwrapper.TorWrapper; import org.briarproject.onionwrapper.TorWrapper;
import org.briarproject.onionwrapper.UnixTorWrapper;
import java.io.File; import java.io.File;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@@ -79,6 +80,6 @@ public class MacTorPluginFactory extends TorPluginFactory {
return new TorPlugin(ioExecutor, wakefulIoExecutor, networkManager, return new TorPlugin(ioExecutor, wakefulIoExecutor, networkManager,
locationUtils, torSocketFactory, circumventionProvider, locationUtils, torSocketFactory, circumventionProvider,
batteryManager, backoff, torRendezvousCrypto, tor, callback, batteryManager, backoff, torRendezvousCrypto, tor, callback,
MAX_LATENCY, MAX_IDLE_TIME); MAX_LATENCY, MAX_IDLE_TIME, true);
} }
} }

View File

@@ -81,6 +81,6 @@ public class UnixTorPluginFactory extends TorPluginFactory {
return new TorPlugin(ioExecutor, wakefulIoExecutor, networkManager, return new TorPlugin(ioExecutor, wakefulIoExecutor, networkManager,
locationUtils, torSocketFactory, circumventionProvider, locationUtils, torSocketFactory, circumventionProvider,
batteryManager, backoff, torRendezvousCrypto, tor, callback, batteryManager, backoff, torRendezvousCrypto, tor, callback,
MAX_LATENCY, MAX_IDLE_TIME); MAX_LATENCY, MAX_IDLE_TIME, true);
} }
} }

View File

@@ -78,6 +78,6 @@ public class WindowsTorPluginFactory extends TorPluginFactory {
return new TorPlugin(ioExecutor, wakefulIoExecutor, networkManager, return new TorPlugin(ioExecutor, wakefulIoExecutor, networkManager,
locationUtils, torSocketFactory, circumventionProvider, locationUtils, torSocketFactory, circumventionProvider,
batteryManager, backoff, torRendezvousCrypto, tor, callback, batteryManager, backoff, torRendezvousCrypto, tor, callback,
MAX_LATENCY, MAX_IDLE_TIME); MAX_LATENCY, MAX_IDLE_TIME, true);
} }
} }

View File

@@ -3,16 +3,18 @@ dependencyVerification {
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db', 'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79', 'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7', 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger-compiler:2.51.1:dagger-compiler-2.51.1.jar:14cf2def1c4c8cd3b977840e297b463191d537cd1c8330992ca5c0b341a641ad', 'com.google.dagger:dagger-compiler:2.45:dagger-compiler-2.45.jar:5617dfb994537dba5b41f3744a6dd13ec3cd99789c065e0d5c6fa9f21cf7ca25',
'com.google.dagger:dagger-spi:2.51.1:dagger-spi-2.51.1.jar:deb52030b92b27c5dcd76b2c0747f1cf105b60939f6073b43eb06cfe7c9ba601', 'com.google.dagger:dagger-producers:2.45:dagger-producers-2.45.jar:a05abb4c3ccf6bb0f056bdcb5ef973898ecf172952ab5948a824aeea6c86ecaa',
'com.google.dagger:dagger:2.51.1:dagger-2.51.1.jar:c3891a4c4a4e48682888ca321eaf8497004b286e1d9a2936867373219f7dd86d', 'com.google.dagger:dagger-spi:2.45:dagger-spi-2.45.jar:7cd6f0b09d88e64a9c97bc80e544ab8ac8fdee9301754413585a74cf64222b27',
'com.google.devtools.ksp:symbol-processing-api:1.9.20-1.0.14:symbol-processing-api-1.9.20-1.0.14.jar:d0339396f40dc9eb3b3f7bc86257f93869ee23448fa31ec4a1de900c6b7ae6d7', 'com.google.dagger:dagger:2.45:dagger-2.45.jar:f011cae7d2c0fb7ea17c34e05bc10e768b1081a5892ad019cf1fdb0e125c49c1',
'com.google.errorprone:error_prone_annotations:2.23.0:error_prone_annotations-2.23.0.jar:ec6f39f068b6ff9ac323c68e28b9299f8c0a80ca512dccb1d4a70f40ac3ec054', 'com.google.devtools.ksp:symbol-processing-api:1.7.0-1.0.6:symbol-processing-api-1.7.0-1.0.6.jar:adc29417be5ca9ff42118105fea4e36d9ef44987abfc41432309371a60198941',
'com.google.errorprone:error_prone_annotations:2.7.1:error_prone_annotations-2.7.1.jar:cd5257c08a246cf8628817ae71cb822be192ef91f6881ca4a3fcff4f1de1cff3',
'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30', 'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30',
'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e', 'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e',
'com.google.guava:failureaccess:1.0.2:failureaccess-1.0.2.jar:8a8f81cf9b359e3f6dfa691a1e776985c061ef2f223c9b2c80753e1b458e8064', 'com.google.guava:failureaccess:1.0.1:failureaccess-1.0.1.jar:a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26',
'com.google.guava:guava:33.0.0-jre:guava-33.0.0-jre.jar:f4d85c3e4d411694337cb873abea09b242b664bb013320be6105327c45991537', 'com.google.guava:guava:31.0.1-jre:guava-31.0.1-jre.jar:d5be94d65e87bd219fb3193ad1517baa55a3b88fc91d21cf735826ab5af087b9',
'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99', 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
'com.google.j2objc:j2objc-annotations:1.3:j2objc-annotations-1.3.jar:21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b',
'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291', 'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
'com.squareup:kotlinpoet:1.11.0:kotlinpoet-1.11.0.jar:2887ada1ca03dd83baa2758640d87e840d1907564db0ef88d2289c868a980492', 'com.squareup:kotlinpoet:1.11.0:kotlinpoet-1.11.0.jar:2887ada1ca03dd83baa2758640d87e840d1907564db0ef88d2289c868a980492',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
@@ -25,17 +27,19 @@ dependencyVerification {
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047', 'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
'org.briarproject:jtorctl:0.5:jtorctl-0.5.jar:43f8c7d390169772b9a2c82ab806c8414c136a2a8636c555e22754bb7260793b', 'org.briarproject:jtorctl:0.5:jtorctl-0.5.jar:43f8c7d390169772b9a2c82ab806c8414c136a2a8636c555e22754bb7260793b',
'org.briarproject:null-safety:0.1:null-safety-0.1.jar:161760de5e838cb982bafa973df820675d4397098e9a91637a36a306d43ba011', 'org.briarproject:null-safety:0.1:null-safety-0.1.jar:161760de5e838cb982bafa973df820675d4397098e9a91637a36a306d43ba011',
'org.briarproject:onionwrapper-core:0.1.3:onionwrapper-core-0.1.3.jar:32d08c9d81a9591e08d7e64e3569334fee21f503b00514006f2e6cbbd409d0df', 'org.briarproject:onionwrapper-core:0.0.5:onionwrapper-core-0.0.5.jar:9071678323535cb3dfe0f3add96066037db43ea024333eba0117c759bcbd8d63',
'org.briarproject:onionwrapper-java:0.1.3:onionwrapper-java-0.1.3.jar:a6bc535e8ea55e567c932f23123eabd10ad53251d3a1e5648960b177e7ab209b', 'org.briarproject:onionwrapper-java:0.0.5:onionwrapper-java-0.0.5.jar:19503ce1dd661f7119eee8ccd2f22b667a28d746c862dc5bb3d2e476db47e27d',
'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a', 'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a',
'org.checkerframework:checker-qual:3.41.0:checker-qual-3.41.0.jar:2f9f245bf68e4259d610894f2406dc1f6363dc639302bd566e8272e4f4541172', 'org.checkerframework:checker-qual:3.12.0:checker-qual-3.12.0.jar:ff10785ac2a357ec5de9c293cb982a2cbb605c0309ea4cc1cb9b9bc6dbe7f3cb',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9', 'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21', 'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050', 'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
'org.jetbrains.kotlin:kotlin-reflect:1.6.10:kotlin-reflect-1.6.10.jar:3277ac102ae17aad10a55abec75ff5696c8d109790396434b496e75087854203', 'org.jetbrains.kotlin:kotlin-reflect:1.6.10:kotlin-reflect-1.6.10.jar:3277ac102ae17aad10a55abec75ff5696c8d109790396434b496e75087854203',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.0:kotlin-stdlib-jdk7-1.9.0.jar:b7979a7aac94055f0d9f1fd3b47ce5ffe1cb6032a842ba9fbe7186f085289178', 'org.jetbrains.kotlin:kotlin-stdlib-common:1.7.0:kotlin-stdlib-common-1.7.0.jar:59c6ff64fe9a6604afce03e8aaa75f83586c6030ac71fb0b34ee7cdefed3618f',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.0:kotlin-stdlib-jdk8-1.9.0.jar:a59fa24fdf1ffb594baecdbf0fd10010f977cea10236d487fe3464977a7377fa', 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.0:kotlin-stdlib-jdk7-1.7.0.jar:07e91be9b2ca20672d2bdb7e181b766e73453a2da13492b5ddaee8fa47aea239',
'org.jetbrains.kotlin:kotlin-stdlib:1.9.20:kotlin-stdlib-1.9.20.jar:28a35bcdff46d864f80f346a617e486284b208d17378c41900dfb1de95a90e6c', 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.0:kotlin-stdlib-jdk8-1.7.0.jar:cf058e11db1dfc9944680c8c61b95ac689aaaa8a3eb30bced028100f038f030b',
'org.jetbrains.kotlin:kotlin-stdlib:1.7.0:kotlin-stdlib-1.7.0.jar:aa88e9625577957f3249a46cb6e166ee09b369e600f7a11d148d16b0a6d87f05',
'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.5.0:kotlinx-metadata-jvm-0.5.0.jar:ca063a96639b08b9eaa0de4d65e899480740a6efbe28ab9a8681a2ced03055a4',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478', 'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09', 'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b', 'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',

View File

@@ -1,6 +1,6 @@
[main] [main]
host = https://www.transifex.com host = https://www.transifex.com
lang_map = es_CU: es-rCU, pt_BR: pt-rBR, pt_PT: pt-rPT, nb_NO: nb, zh-Hans: zh-rCN, zh-Hant: zh-rTW lang_map = pt_BR: pt-rBR, nb_NO: nb, zh-Hans: zh-rCN, zh-Hant: zh-rTW
[o:otf:p:briar:r:google-play-full-description] [o:otf:p:briar:r:google-play-full-description]
file_filter = fastlane/metadata/android/<lang>/full_description.txt file_filter = fastlane/metadata/android/<lang>/full_description.txt

View File

@@ -16,27 +16,36 @@ def getStdout = { command, defaultValue ->
} }
android { android {
compileSdk 34 compileSdkVersion 33
buildToolsVersion '34.0.0' buildToolsVersion '33.0.0'
packagingOptions { packagingOptions {
doNotStrip '**/*.so' doNotStrip '**/*.so'
jniLibs {
// Unpack native libs from the APK rather than using them in-place. We package the
// Tor binaries as native libs and need them to be unpacked so we can execute them
useLegacyPackaging = true
}
} }
defaultConfig { defaultConfig {
// FIXME: sqlite-jdbc-crypt uses __register_atfork which is only available on API >= 23.
// We might be able to solve this by recompiling (or asking upstream to recompile)
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 34 targetSdkVersion 33
versionCode 10514 versionCode 10506
versionName "1.5.14" versionName "1.5.6"
applicationId "org.briarproject.briar.android" applicationId "org.briarproject.briar.android"
buildConfigField "String", "TorVersion", "\"$tor_version\""
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
buildConfigField "String", "TorVersion", "\"$tor_version\""
buildConfigField "String", "GitHash", buildConfigField "String", "GitHash",
"\"${getStdout(['git', 'rev-parse', '--short=7', 'HEAD'], 'No commit hash')}\"" "\"${getStdout(['git', 'rev-parse', '--short=7', 'HEAD'], 'No commit hash')}\""
def now = (long) (System.currentTimeMillis() / 1000) def now = (long) (System.currentTimeMillis() / 1000)
buildConfigField "Long", "BuildTimestamp", buildConfigField "Long", "BuildTimestamp",
"${getStdout(['git', 'log', '-n', '1', '--format=%ct'], now)}000L" "${getStdout(['git', 'log', '-n', '1', '--format=%ct'], now)}000L"
testInstrumentationRunner 'org.briarproject.briar.android.BriarTestRunner' testInstrumentationRunner 'org.briarproject.briar.android.BriarTestRunner'
testInstrumentationRunnerArguments disableAnalytics: 'true' testInstrumentationRunnerArguments disableAnalytics: 'true'
} }
@@ -78,6 +87,7 @@ android {
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
coreLibraryDesugaringEnabled true
} }
testOptions { testOptions {
@@ -97,6 +107,10 @@ android {
} }
} }
// Workaround for https://github.com/gradle/gradle/issues/20330 to make gradle-witness work
// with Android Gradle Plugin 7.4
project.evaluationDependsOn(project.getRootProject().findProject("bramble-android").getPath())
dependencies { dependencies {
// In theory this dependency shouldn't be needed, but without it Android Studio's linter will // In theory this dependency shouldn't be needed, but without it Android Studio's linter will
// complain about unresolved symbols for bramble-api test classes in briar-android tests, // complain about unresolved symbols for bramble-api test classes in briar-android tests,
@@ -108,15 +122,16 @@ dependencies {
implementation project(':bramble-android') implementation project(':bramble-android')
implementation project(':briar-core') implementation project(':briar-core')
// newer versions of the libraries below require compileSdk 34 implementation 'androidx.fragment:fragment:1.5.5'
implementation 'androidx.fragment:fragment:1.6.2' implementation 'androidx.preference:preference:1.2.0'
implementation 'androidx.preference:preference:1.2.1' implementation 'androidx.exifinterface:exifinterface:1.3.6'
implementation 'androidx.exifinterface:exifinterface:1.3.7' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2' implementation 'androidx.lifecycle:lifecycle-livedata:2.5.1'
implementation 'androidx.lifecycle:lifecycle-livedata:2.6.2'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.google.android.material:material:1.9.0' // check https://github.com/material-components/material-components-android/issues/3191
// before upgrading material library
implementation 'com.google.android.material:material:1.7.0'
implementation 'androidx.recyclerview:recyclerview-selection:1.1.0' implementation 'androidx.recyclerview:recyclerview-selection:1.1.0'
// force kotlin standard lib to latest version to prevent jetifier issues // force kotlin standard lib to latest version to prevent jetifier issues
@@ -130,7 +145,7 @@ dependencies {
implementation 'com.vanniktech:emoji-google:0.9.0' // newer versions are more work to adapt implementation 'com.vanniktech:emoji-google:0.9.0' // newer versions are more work to adapt
implementation 'com.github.kobakei:MaterialFabSpeedDial:1.2.1' implementation 'com.github.kobakei:MaterialFabSpeedDial:1.2.1'
implementation 'com.github.chrisbanes:PhotoView:2.3.0' implementation 'com.github.chrisbanes:PhotoView:2.3.0'
def glideVersion = '4.16.0' def glideVersion = '4.14.2'
implementation("com.github.bumptech.glide:glide:$glideVersion") { implementation("com.github.bumptech.glide:glide:$glideVersion") {
exclude group: 'com.android.support' exclude group: 'com.android.support'
exclude module: 'disklrucache' // when there's no disk cache, we can't accidentally use it exclude module: 'disklrucache' // when there's no disk cache, we can't accidentally use it
@@ -142,6 +157,8 @@ dependencies {
compileOnly 'javax.annotation:jsr250-api:1.0' compileOnly 'javax.annotation:jsr250-api:1.0'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
testImplementation project(path: ':bramble-api', configuration: 'testOutput') testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation project(path: ':bramble-core', configuration: 'testOutput') testImplementation project(path: ':bramble-core', configuration: 'testOutput')

View File

@@ -25,8 +25,9 @@
-dontnote com.android.org.conscrypt.SSLParametersImpl -dontnote com.android.org.conscrypt.SSLParametersImpl
-dontnote org.apache.harmony.xnet.provider.jsse.SSLParametersImpl -dontnote org.apache.harmony.xnet.provider.jsse.SSLParametersImpl
-dontnote sun.security.ssl.SSLContextImpl -dontnote sun.security.ssl.SSLContextImpl
-dontwarn org.conscrypt.OpenSSLProvider -dontwarn org.bouncycastle.jsse.**
-dontwarn org.conscrypt.Conscrypt -dontwarn org.conscrypt.**
-dontwarn org.openjsse.**
# HTML sanitiser # HTML sanitiser
-keep class org.jsoup.safety.Whitelist -keep class org.jsoup.safety.Whitelist

View File

@@ -33,18 +33,11 @@
tools:ignore="ScopedStorage" /> tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission-sdk-23 <uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION"
android:name="android.permission.ACCESS_FINE_LOCATION"
android:maxSdkVersion="32" /> android:maxSdkVersion="32" />
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> <uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission-sdk-23 android:name="android.permission.USE_BIOMETRIC" /> <uses-permission-sdk-23 android:name="android.permission.USE_BIOMETRIC" />
<uses-permission-sdk-23 android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission-sdk-23 android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission-sdk-23 android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" />
<uses-permission-sdk-23 android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission
android:name="android.permission.HIDE_OVERLAY_WINDOWS"
tools:targetApi="31" />
<application <application
android:name="org.briarproject.briar.android.BriarApplicationImpl" android:name="org.briarproject.briar.android.BriarApplicationImpl"
@@ -70,8 +63,7 @@
<service <service
android:name="org.briarproject.briar.android.BriarService" android:name="org.briarproject.briar.android.BriarService"
android:exported="false" android:exported="false">
android:foregroundServiceType="connectedDevice|dataSync">
<intent-filter> <intent-filter>
<action android:name="org.briarproject.briar.android.BriarService" /> <action android:name="org.briarproject.briar.android.BriarService" />
</intent-filter> </intent-filter>
@@ -112,12 +104,12 @@
<activity <activity
android:name="org.briarproject.briar.android.login.StartupActivity" android:name="org.briarproject.briar.android.login.StartupActivity"
android:exported="false" android:exported="false"
android:theme="@style/BriarTheme.NoActionBar" /> android:label="@string/app_name" />
<activity <activity
android:name="org.briarproject.briar.android.account.SetupActivity" android:name="org.briarproject.briar.android.account.SetupActivity"
android:exported="false" android:exported="false"
android:theme="@style/BriarTheme.NoActionBar" /> android:label="@string/setup_title" />
<activity <activity
android:name="org.briarproject.briar.android.splash.SplashScreenActivity" android:name="org.briarproject.briar.android.splash.SplashScreenActivity"

View File

@@ -27,7 +27,7 @@ class BriarAccountManager extends AndroidAccountManager {
super.deleteAccount(); super.deleteAccount();
Localizer.reinitialize(); Localizer.reinitialize();
UiUtils.setTheme(appContext, UiUtils.setTheme(appContext,
appContext.getString(R.string.pref_theme_system_value)); appContext.getString(R.string.pref_theme_light_value));
} }
} }
} }

View File

@@ -150,7 +150,8 @@ public class AppModule {
//FIXME: StrictMode //FIXME: StrictMode
StrictMode.ThreadPolicy tp = StrictMode.allowThreadDiskReads(); StrictMode.ThreadPolicy tp = StrictMode.allowThreadDiskReads();
StrictMode.allowThreadDiskWrites(); StrictMode.allowThreadDiskWrites();
File dbDir = app.getApplicationContext().getDir("db", MODE_PRIVATE); File dbDir = app.getApplicationContext().getDir("db_sqlite",
MODE_PRIVATE);
File keyDir = app.getApplicationContext().getDir("key", MODE_PRIVATE); File keyDir = app.getApplicationContext().getDir("key", MODE_PRIVATE);
StrictMode.setThreadPolicy(tp); StrictMode.setThreadPolicy(tp);
KeyStrengthener keyStrengthener = SDK_INT >= 23 KeyStrengthener keyStrengthener = SDK_INT >= 23

View File

@@ -33,7 +33,6 @@ import static java.util.logging.Level.FINE;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD; import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
import static org.briarproject.briar.android.settings.DisplayFragment.PREF_THEME;
public class BriarApplicationImpl extends Application public class BriarApplicationImpl extends Application
implements BriarApplication { implements BriarApplication {
@@ -110,11 +109,11 @@ public class BriarApplicationImpl extends Application
} }
private void setTheme(Context ctx, SharedPreferences prefs) { private void setTheme(Context ctx, SharedPreferences prefs) {
String theme = prefs.getString(PREF_THEME, null); String theme = prefs.getString("pref_key_theme", null);
if (theme == null) { if (theme == null) {
// set default value // set default value
theme = getString(R.string.pref_theme_system_value); theme = getString(R.string.pref_theme_light_value);
prefs.edit().putString(PREF_THEME, theme).apply(); prefs.edit().putString("pref_key_theme", theme).apply();
} }
// set theme // set theme
UiUtils.setTheme(ctx, theme); UiUtils.setTheme(ctx, theme);

View File

@@ -22,7 +22,6 @@ import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult; import org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult;
import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.AndroidUtils;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.logout.HideUiActivity; import org.briarproject.briar.android.logout.HideUiActivity;
import org.briarproject.briar.api.android.AndroidNotificationManager; import org.briarproject.briar.api.android.AndroidNotificationManager;
@@ -175,8 +174,7 @@ public class BriarService extends Service {
filter.addAction(ACTION_SHUTDOWN); filter.addAction(ACTION_SHUTDOWN);
filter.addAction("android.intent.action.QUICKBOOT_POWEROFF"); filter.addAction("android.intent.action.QUICKBOOT_POWEROFF");
filter.addAction("com.htc.intent.action.QUICKBOOT_POWEROFF"); filter.addAction("com.htc.intent.action.QUICKBOOT_POWEROFF");
AndroidUtils.registerReceiver(getApplicationContext(), receiver, registerReceiver(receiver, filter);
filter);
}, "LifecycleStartup"); }, "LifecycleStartup");
} }
@@ -217,14 +215,17 @@ public class BriarService extends Service {
@Override @Override
public void onDestroy() { public void onDestroy() {
// Hold a wake lock during shutdown
wakeLockManager.runWakefully(() -> {
super.onDestroy(); super.onDestroy();
LOG.info("Destroyed"); LOG.info("Destroyed");
// Stop the lifecycle, if not already stopped
shutdown(false);
stopForeground(true); stopForeground(true);
if (receiver != null) { if (receiver != null) unregisterReceiver(receiver);
getApplicationContext().unregisterReceiver(receiver); // Stop the services in a background thread
} wakeLockManager.executeWakefully(() -> {
if (started) lifecycleManager.stopServices();
}, "LifecycleShutdown");
}, "LifecycleShutdown");
} }
@Override @Override
@@ -294,8 +295,8 @@ public class BriarService extends Service {
private void shutdownFromBackground() { private void shutdownFromBackground() {
// Hold a wake lock during shutdown // Hold a wake lock during shutdown
wakeLockManager.runWakefully(() -> { wakeLockManager.runWakefully(() -> {
// Begin lifecycle shutdown // Stop the service
shutdown(true); stopSelf();
// Hide the UI // Hide the UI
hideUi(); hideUi();
// Wait for shutdown to complete, then exit // Wait for shutdown to complete, then exit
@@ -330,18 +331,8 @@ public class BriarService extends Service {
/** /**
* Starts the shutdown process. * Starts the shutdown process.
*/ */
public void shutdown(boolean stopAndroidService) { public void shutdown() {
// Hold a wake lock during shutdown stopSelf(); // This will call onDestroy()
wakeLockManager.runWakefully(() -> {
// Stop the lifecycle services in a background thread,
// then stop this Android service if needed
wakeLockManager.executeWakefully(() -> {
if (started) lifecycleManager.stopServices();
if (stopAndroidService) {
androidExecutor.runOnUiThread(() -> stopSelf());
}
}, "LifecycleShutdown");
}, "LifecycleShutdown");
} }
public class BriarBinder extends Binder { public class BriarBinder extends Binder {

View File

@@ -21,7 +21,6 @@ import static android.os.PowerManager.ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED;
import static android.os.PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED; import static android.os.PowerManager.ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.AndroidUtils.registerReceiver;
class DozeWatchdogImpl implements DozeWatchdog, Service { class DozeWatchdogImpl implements DozeWatchdog, Service {
@@ -49,7 +48,7 @@ class DozeWatchdogImpl implements DozeWatchdog, Service {
filter.addAction(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED); filter.addAction(ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED);
filter.addAction(ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED); filter.addAction(ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED);
} }
registerReceiver(appContext, receiver, filter); appContext.registerReceiver(receiver, filter);
} }
@Override @Override

View File

@@ -49,7 +49,6 @@ import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.content.pm.PackageManager.GET_SIGNATURES; import static android.content.pm.PackageManager.GET_SIGNATURES;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.AndroidUtils.registerReceiver;
import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault @NotNullByDefault
@@ -208,7 +207,7 @@ class ScreenFilterMonitorImpl implements ScreenFilterMonitor, Service {
filter.addAction(ACTION_PACKAGE_REPLACED); filter.addAction(ACTION_PACKAGE_REPLACED);
filter.addDataScheme("package"); filter.addDataScheme("package");
receiver = new PackageBroadcastReceiver(); receiver = new PackageBroadcastReceiver();
registerReceiver(app, receiver, filter); app.registerReceiver(receiver, filter);
cachedApps = null; cachedApps = null;
}); });
} }

View File

@@ -18,9 +18,7 @@ import javax.annotation.Nullable;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.util.StringUtils.toUtf8; import static org.briarproject.bramble.util.StringUtils.toUtf8;
import static org.briarproject.briar.android.util.UiUtils.hideViewOnSmallScreen;
import static org.briarproject.briar.android.util.UiUtils.setError; import static org.briarproject.briar.android.util.UiUtils.setError;
import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
@@ -40,27 +38,19 @@ public class AuthorNameFragment extends SetupFragment {
public View onCreateView(LayoutInflater inflater, public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) { @Nullable Bundle savedInstanceState) {
requireActivity().setTitle(getString(R.string.setup_title));
View v = inflater.inflate(R.layout.fragment_setup_author_name, View v = inflater.inflate(R.layout.fragment_setup_author_name,
container, false); container, false);
authorNameWrapper = v.findViewById(R.id.nickname_entry_wrapper); authorNameWrapper = v.findViewById(R.id.nickname_entry_wrapper);
authorNameInput = v.findViewById(R.id.nickname_entry); authorNameInput = v.findViewById(R.id.nickname_entry);
Button infoButton = v.findViewById(R.id.info_button);
nextButton = v.findViewById(R.id.next); nextButton = v.findViewById(R.id.next);
authorNameInput.addTextChangedListener(this); authorNameInput.addTextChangedListener(this);
infoButton.setOnClickListener(view ->
showOnboardingDialog(requireContext(), getHelpText()));
nextButton.setOnClickListener(this); nextButton.setOnClickListener(this);
return v; return v;
} }
@Override
public void onStart() {
super.onStart();
hideViewOnSmallScreen(requireView().findViewById(R.id.logo));
}
@Override @Override
public String getUniqueTag() { public String getUniqueTag() {
return TAG; return TAG;

View File

@@ -23,7 +23,6 @@ import static android.view.View.VISIBLE;
import static android.widget.Toast.LENGTH_LONG; import static android.widget.Toast.LENGTH_LONG;
import static org.briarproject.android.dontkillmelib.DozeUtils.getDozeWhitelistingIntent; import static org.briarproject.android.dontkillmelib.DozeUtils.getDozeWhitelistingIntent;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_DOZE_WHITELISTING; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_DOZE_WHITELISTING;
import static org.briarproject.briar.android.util.UiUtils.hideViewOnSmallScreen;
import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog; import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@@ -80,12 +79,6 @@ public class DozeFragment extends SetupFragment
return v; return v;
} }
@Override
public void onStart() {
super.onStart();
hideViewOnSmallScreen(requireView().findViewById(R.id.logo));
}
@Override @Override
public String getUniqueTag() { public String getUniqueTag() {
return TAG; return TAG;

View File

@@ -28,12 +28,10 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static android.view.View.INVISIBLE; import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE; import static android.view.View.VISIBLE;
import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
import static androidx.core.content.ContextCompat.checkSelfPermission; import static androidx.core.content.ContextCompat.checkSelfPermission;
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK; import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.STRONG;
import static org.briarproject.briar.android.util.UiUtils.hideViewOnSmallScreen;
import static org.briarproject.briar.android.util.UiUtils.setError; import static org.briarproject.briar.android.util.UiUtils.setError;
import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
@@ -59,6 +57,7 @@ public class SetPasswordFragment extends SetupFragment {
public View onCreateView(LayoutInflater inflater, public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) { @Nullable Bundle savedInstanceState) {
requireActivity().setTitle(getString(R.string.setup_password_intro));
View v = inflater.inflate(R.layout.fragment_setup_password, container, View v = inflater.inflate(R.layout.fragment_setup_password, container,
false); false);
@@ -68,18 +67,17 @@ public class SetPasswordFragment extends SetupFragment {
passwordConfirmationWrapper = passwordConfirmationWrapper =
v.findViewById(R.id.password_confirm_wrapper); v.findViewById(R.id.password_confirm_wrapper);
passwordConfirmation = v.findViewById(R.id.password_confirm); passwordConfirmation = v.findViewById(R.id.password_confirm);
Button infoButton = v.findViewById(R.id.info_button);
nextButton = v.findViewById(R.id.next); nextButton = v.findViewById(R.id.next);
ProgressBar progressBar = v.findViewById(R.id.progress); ProgressBar progressBar = v.findViewById(R.id.progress);
passwordEntry.addTextChangedListener(this); passwordEntry.addTextChangedListener(this);
passwordConfirmation.addTextChangedListener(this); passwordConfirmation.addTextChangedListener(this);
infoButton.setOnClickListener(view ->
showOnboardingDialog(requireContext(), getHelpText()));
nextButton.setOnClickListener(this); nextButton.setOnClickListener(this);
if (!viewModel.needToShowDozeFragment()) { if (!viewModel.needToShowDozeFragment()) {
nextButton.setText(R.string.create_account_button); nextButton.setText(R.string.create_account_button);
int options = passwordConfirmation.getImeOptions();
passwordConfirmation.setImeOptions(options | IME_ACTION_DONE);
} }
viewModel.getIsCreatingAccount() viewModel.getIsCreatingAccount()
@@ -96,12 +94,6 @@ public class SetPasswordFragment extends SetupFragment {
return v; return v;
} }
@Override
public void onStart() {
super.onStart();
hideViewOnSmallScreen(requireView().findViewById(R.id.logo));
}
@Override @Override
public String getUniqueTag() { public String getUniqueTag() {
return TAG; return TAG;
@@ -118,27 +110,17 @@ public class SetPasswordFragment extends SetupFragment {
String password2 = passwordConfirmation.getText().toString(); String password2 = passwordConfirmation.getText().toString();
boolean passwordsMatch = password1.equals(password2); boolean passwordsMatch = password1.equals(password2);
strengthMeter.setVisibility(!password1.isEmpty() ? VISIBLE : INVISIBLE); strengthMeter
.setVisibility(password1.length() > 0 ? VISIBLE : INVISIBLE);
float strength = viewModel.estimatePasswordStrength(password1); float strength = viewModel.estimatePasswordStrength(password1);
strengthMeter.setStrength(strength); strengthMeter.setStrength(strength);
boolean strongEnough = strength >= QUITE_WEAK; boolean strongEnough = strength >= QUITE_WEAK;
if (!password1.isEmpty()) {
if (strength >= STRONG) {
passwordEntryWrapper.setHelperText(
getString(R.string.password_strong));
} else if (strength >= QUITE_WEAK) {
passwordEntryWrapper.setHelperText(
getString(R.string.password_quite_strong));
} else {
passwordEntryWrapper.setHelperTextEnabled(false);
}
}
setError(passwordEntryWrapper, getString(R.string.password_too_weak), setError(passwordEntryWrapper, getString(R.string.password_too_weak),
!password1.isEmpty() && !strongEnough); password1.length() > 0 && !strongEnough);
setError(passwordConfirmationWrapper, setError(passwordConfirmationWrapper,
getString(R.string.passwords_do_not_match), getString(R.string.passwords_do_not_match),
!password2.isEmpty() && !passwordsMatch); password2.length() > 0 && !passwordsMatch);
boolean enabled = passwordsMatch && strongEnough; boolean enabled = passwordsMatch && strongEnough;
nextButton.setEnabled(enabled); nextButton.setEnabled(enabled);

View File

@@ -1,6 +1,5 @@
package org.briarproject.briar.android.account; package org.briarproject.briar.android.account;
import android.annotation.SuppressLint;
import android.app.KeyguardManager; import android.app.KeyguardManager;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.Intent; import android.content.Intent;
@@ -114,7 +113,6 @@ public class UnlockActivity extends BaseActivity {
} }
@Override @Override
@SuppressLint("MissingSuperCall")
public void onBackPressed() { public void onBackPressed() {
moveTaskToBack(true); moveTaskToBack(true);
} }

View File

@@ -101,8 +101,6 @@ public abstract class BaseActivity extends AppCompatActivity
// unlock screen is shown. // unlock screen is shown.
if (PREVENT_SCREENSHOTS) getWindow().addFlags(FLAG_SECURE); if (PREVENT_SCREENSHOTS) getWindow().addFlags(FLAG_SECURE);
if (SDK_INT >= 31) getWindow().setHideOverlayWindows(true);
for (ActivityLifecycleController alc : lifecycleControllers) { for (ActivityLifecycleController alc : lifecycleControllers) {
alc.onActivityCreate(this); alc.onActivityCreate(this);
} }

View File

@@ -7,8 +7,6 @@ import android.view.Window;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.Toast; import android.widget.Toast;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.android.dontkillmelib.wakelock.AndroidWakeLockManager; import org.briarproject.android.dontkillmelib.wakelock.AndroidWakeLockManager;
import org.briarproject.bramble.api.system.Wakeful; import org.briarproject.bramble.api.system.Wakeful;
import org.briarproject.briar.R; import org.briarproject.briar.R;
@@ -179,8 +177,8 @@ public abstract class BriarActivity extends BaseActivity {
} }
protected void showDozeDialog(@StringRes int message) { protected void showDozeDialog(@StringRes int message) {
MaterialAlertDialogBuilder b = AlertDialog.Builder b =
new MaterialAlertDialogBuilder(this, R.style.BriarDialogTheme); new AlertDialog.Builder(this, R.style.BriarDialogTheme);
b.setMessage(message); b.setMessage(message);
b.setView(R.layout.checkbox); b.setView(R.layout.checkbox);
b.setPositiveButton(R.string.fix, b.setPositiveButton(R.string.fix,

View File

@@ -10,8 +10,6 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Toast; import android.widget.Toast;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.activity.ActivityComponent;
@@ -29,6 +27,7 @@ import javax.inject.Inject;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.UiThread; import androidx.annotation.UiThread;
import androidx.appcompat.app.AlertDialog;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView.LayoutManager; import androidx.recyclerview.widget.RecyclerView.LayoutManager;
@@ -221,8 +220,8 @@ public class BlogFragment extends BaseFragment
} }
private void showDeleteDialog() { private void showDeleteDialog() {
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder( AlertDialog.Builder builder = new AlertDialog.Builder(requireContext(),
requireContext(), R.style.BriarDialogTheme); R.style.BriarDialogTheme);
builder.setTitle(getString(R.string.blogs_remove_blog)); builder.setTitle(getString(R.string.blogs_remove_blog));
builder.setMessage( builder.setMessage(
getString(R.string.blogs_remove_blog_dialog_message)); getString(R.string.blogs_remove_blog_dialog_message));

View File

@@ -4,8 +4,6 @@ import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.BaseActivity; import org.briarproject.briar.android.activity.BaseActivity;
@@ -15,6 +13,7 @@ import org.briarproject.nullsafety.ParametersNotNullByDefault;
import javax.inject.Inject; import javax.inject.Inject;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment; import androidx.fragment.app.DialogFragment;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
@@ -52,8 +51,8 @@ public class RssFeedDeleteFeedDialogFragment extends DialogFragment {
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
GroupId groupId = new GroupId( GroupId groupId = new GroupId(
requireNonNull(requireArguments().getByteArray(GROUP_ID))); requireNonNull(requireArguments().getByteArray(GROUP_ID)));
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder( AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity(),
requireActivity(), R.style.BriarDialogTheme); R.style.BriarDialogTheme);
builder.setTitle(getString(R.string.blogs_rss_remove_feed)); builder.setTitle(getString(R.string.blogs_rss_remove_feed));
builder.setMessage( builder.setMessage(
getString(R.string.blogs_rss_remove_feed_dialog_message)); getString(R.string.blogs_rss_remove_feed_dialog_message));

View File

@@ -4,8 +4,6 @@ import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.BaseActivity; import org.briarproject.briar.android.activity.BaseActivity;
import org.briarproject.nullsafety.MethodsNotNullByDefault; import org.briarproject.nullsafety.MethodsNotNullByDefault;
@@ -14,6 +12,7 @@ import org.briarproject.nullsafety.ParametersNotNullByDefault;
import javax.inject.Inject; import javax.inject.Inject;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment; import androidx.fragment.app.DialogFragment;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
@@ -48,8 +47,8 @@ public class RssFeedImportFailedDialogFragment extends DialogFragment {
@Override @Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
MaterialAlertDialogBuilder builder = AlertDialog.Builder builder =
new MaterialAlertDialogBuilder(requireActivity(), new AlertDialog.Builder(requireActivity(),
R.style.BriarDialogTheme); R.style.BriarDialogTheme);
builder.setMessage(R.string.blogs_rss_feeds_import_error); builder.setMessage(R.string.blogs_rss_feeds_import_error);
builder.setNegativeButton(R.string.cancel, null); builder.setNegativeButton(R.string.cancel, null);

View File

@@ -88,7 +88,6 @@ import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED; import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED;
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE; import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING; import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING;
import static org.briarproject.bramble.util.AndroidUtils.registerReceiver;
import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.StringUtils.ISO_8859_1; import static org.briarproject.bramble.util.StringUtils.ISO_8859_1;
import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactPermissionManager.areEssentialPermissionsGranted; import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactPermissionManager.areEssentialPermissionsGranted;
@@ -209,7 +208,7 @@ class AddNearbyContactViewModel extends AndroidViewModel
qrCodeDecoder = new QrCodeDecoder(androidExecutor, ioExecutor, this); qrCodeDecoder = new QrCodeDecoder(androidExecutor, ioExecutor, this);
eventBus.addListener(this); eventBus.addListener(this);
IntentFilter filter = new IntentFilter(ACTION_SCAN_MODE_CHANGED); IntentFilter filter = new IntentFilter(ACTION_SCAN_MODE_CHANGED);
registerReceiver(getApplication(), bluetoothReceiver, filter); getApplication().registerReceiver(bluetoothReceiver, filter);
} }
@Override @Override

View File

@@ -1,6 +1,5 @@
package org.briarproject.briar.android.contact.add.remote; package org.briarproject.briar.android.contact.add.remote;
import android.content.ActivityNotFoundException;
import android.content.ClipData; import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.os.Bundle; import android.os.Bundle;
@@ -21,7 +20,6 @@ import org.briarproject.briar.android.view.InfoView;
import org.briarproject.nullsafety.MethodsNotNullByDefault; import org.briarproject.nullsafety.MethodsNotNullByDefault;
import org.briarproject.nullsafety.ParametersNotNullByDefault; import org.briarproject.nullsafety.ParametersNotNullByDefault;
import java.util.logging.Logger;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -31,12 +29,8 @@ import androidx.core.app.ShareCompat.IntentBuilder;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import static android.content.Context.CLIPBOARD_SERVICE; import static android.content.Context.CLIPBOARD_SERVICE;
import static android.widget.Toast.LENGTH_LONG;
import static android.widget.Toast.LENGTH_SHORT; import static android.widget.Toast.LENGTH_SHORT;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.contact.HandshakeLinkConstants.LINK_REGEX; import static org.briarproject.bramble.api.contact.HandshakeLinkConstants.LINK_REGEX;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.briar.android.util.UiUtils.hideViewOnSmallScreen; import static org.briarproject.briar.android.util.UiUtils.hideViewOnSmallScreen;
import static org.briarproject.briar.android.util.UiUtils.observeOnce; import static org.briarproject.briar.android.util.UiUtils.observeOnce;
@@ -45,7 +39,6 @@ import static org.briarproject.briar.android.util.UiUtils.observeOnce;
public class LinkExchangeFragment extends BaseFragment { public class LinkExchangeFragment extends BaseFragment {
private static final String TAG = LinkExchangeFragment.class.getName(); private static final String TAG = LinkExchangeFragment.class.getName();
private static final Logger LOG = getLogger(TAG);
@Inject @Inject
ViewModelProvider.Factory viewModelFactory; ViewModelProvider.Factory viewModelFactory;
@@ -123,18 +116,11 @@ public class LinkExchangeFragment extends BaseFragment {
copyButton.setEnabled(true); copyButton.setEnabled(true);
Button shareButton = v.findViewById(R.id.shareButton); Button shareButton = v.findViewById(R.id.shareButton);
shareButton.setOnClickListener(view -> { shareButton.setOnClickListener(view ->
try {
IntentBuilder.from(requireActivity()) IntentBuilder.from(requireActivity())
.setText(link) .setText(link)
.setType("text/plain") .setType("text/plain")
.startChooser(); .startChooser());
} catch (ActivityNotFoundException e) {
logException(LOG, WARNING, e);
Toast.makeText(requireContext(),
R.string.error_start_activity, LENGTH_LONG).show();
}
});
shareButton.setEnabled(true); shareButton.setEnabled(true);
InfoView infoText = v.findViewById(R.id.infoView); InfoView infoText = v.findViewById(R.id.infoView);

View File

@@ -55,7 +55,6 @@ public class NicknameFragment extends BaseFragment {
private TextInputLayout contactNameLayout; private TextInputLayout contactNameLayout;
private TextInputEditText contactNameInput; private TextInputEditText contactNameInput;
private BriarButton addButton;
@Override @Override
public String getUniqueTag() { public String getUniqueTag() {
@@ -92,7 +91,7 @@ public class NicknameFragment extends BaseFragment {
contactNameLayout = v.findViewById(R.id.contactNameLayout); contactNameLayout = v.findViewById(R.id.contactNameLayout);
contactNameInput = v.findViewById(R.id.contactNameInput); contactNameInput = v.findViewById(R.id.contactNameInput);
addButton = v.findViewById(R.id.addButton); BriarButton addButton = v.findViewById(R.id.addButton);
addButton.setOnClickListener(view -> onAddButtonClicked()); addButton.setOnClickListener(view -> onAddButtonClicked());
return v; return v;
@@ -113,7 +112,7 @@ public class NicknameFragment extends BaseFragment {
@Nullable @Nullable
private String getNicknameOrNull() { private String getNicknameOrNull() {
Editable text = contactNameInput.getText(); Editable text = contactNameInput.getText();
if (text == null || text.toString().trim().isEmpty()) { if (text == null || text.toString().trim().length() == 0) {
contactNameLayout.setError(getString(R.string.nickname_missing)); contactNameLayout.setError(getString(R.string.nickname_missing));
contactNameInput.requestFocus(); contactNameInput.requestFocus();
return null; return null;
@@ -130,10 +129,7 @@ public class NicknameFragment extends BaseFragment {
private void onAddButtonClicked() { private void onAddButtonClicked() {
String name = getNicknameOrNull(); String name = getNicknameOrNull();
if (name == null) { // invalid nickname if (name == null) return; // invalid nickname
addButton.reset();
return;
}
LifecycleOwner owner = getViewLifecycleOwner(); LifecycleOwner owner = getViewLifecycleOwner();
viewModel.getAddContactResult().observe(owner, result -> { viewModel.getAddContactResult().observe(owner, result -> {

View File

@@ -4,7 +4,6 @@ import android.content.DialogInterface.OnClickListener;
import android.os.Bundle; import android.os.Bundle;
import android.view.MenuItem; import android.view.MenuItem;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import org.briarproject.bramble.api.contact.PendingContactId; import org.briarproject.bramble.api.contact.PendingContactId;
@@ -22,6 +21,7 @@ import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
@@ -110,7 +110,7 @@ public class PendingContactListActivity extends BriarActivity
// show warning dialog // show warning dialog
OnClickListener removeListener = (dialog, which) -> OnClickListener removeListener = (dialog, which) ->
removePendingContact(item.getPendingContact().getId()); removePendingContact(item.getPendingContact().getId());
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder( AlertDialog.Builder builder = new AlertDialog.Builder(
PendingContactListActivity.this, R.style.BriarDialogTheme); PendingContactListActivity.this, R.style.BriarDialogTheme);
builder.setTitle( builder.setTitle(
getString(R.string.dialog_title_remove_pending_contact)); getString(R.string.dialog_title_remove_pending_contact));

View File

@@ -147,7 +147,7 @@ public class BriarControllerImpl implements BriarController {
service.waitForStartup(); service.waitForStartup();
// Shut down the service and wait for it to shut down // Shut down the service and wait for it to shut down
LOG.info("Shutting down service"); LOG.info("Shutting down service");
service.shutdown(true); service.shutdown();
service.waitForShutdown(); service.waitForShutdown();
} catch (InterruptedException e) { } catch (InterruptedException e) {
LOG.warning("Interrupted while waiting for service"); LOG.warning("Interrupted while waiting for service");

View File

@@ -19,7 +19,6 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import org.briarproject.bramble.api.FeatureFlags; import org.briarproject.bramble.api.FeatureFlags;
@@ -102,6 +101,7 @@ import javax.inject.Inject;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.UiThread; import androidx.annotation.UiThread;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.ActionMenuView; import androidx.appcompat.widget.ActionMenuView;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
@@ -812,8 +812,8 @@ public class ConversationActivity extends BriarActivity
} }
private void askToDeleteAllMessages() { private void askToDeleteAllMessages() {
MaterialAlertDialogBuilder builder = AlertDialog.Builder builder =
new MaterialAlertDialogBuilder(this, R.style.BriarDialogTheme); new AlertDialog.Builder(this, R.style.BriarDialogTheme);
builder.setTitle(getString(R.string.dialog_title_delete_all_messages)); builder.setTitle(getString(R.string.dialog_title_delete_all_messages));
builder.setMessage( builder.setMessage(
getString(R.string.dialog_message_delete_all_messages)); getString(R.string.dialog_message_delete_all_messages));
@@ -892,8 +892,8 @@ public class ConversationActivity extends BriarActivity
} }
String msg = join(fails, "\n\n"); String msg = join(fails, "\n\n");
// show dialog // show dialog
MaterialAlertDialogBuilder builder = AlertDialog.Builder builder =
new MaterialAlertDialogBuilder(this, R.style.BriarDialogTheme); new AlertDialog.Builder(this, R.style.BriarDialogTheme);
builder.setTitle( builder.setTitle(
getString(R.string.dialog_title_not_all_messages_deleted)); getString(R.string.dialog_title_not_all_messages_deleted));
builder.setMessage(msg); builder.setMessage(msg);
@@ -904,8 +904,8 @@ public class ConversationActivity extends BriarActivity
private void askToRemoveContact() { private void askToRemoveContact() {
DialogInterface.OnClickListener okListener = DialogInterface.OnClickListener okListener =
(dialog, which) -> removeContact(); (dialog, which) -> removeContact();
MaterialAlertDialogBuilder builder = AlertDialog.Builder builder =
new MaterialAlertDialogBuilder(ConversationActivity.this, new AlertDialog.Builder(ConversationActivity.this,
R.style.BriarDialogTheme); R.style.BriarDialogTheme);
builder.setTitle(getString(R.string.dialog_title_delete_contact)); builder.setTitle(getString(R.string.dialog_title_delete_contact));
builder.setMessage( builder.setMessage(

View File

@@ -7,8 +7,6 @@ import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.sharing.ForumSharingStatusActivity; import org.briarproject.briar.android.sharing.ForumSharingStatusActivity;
@@ -22,6 +20,7 @@ import org.briarproject.nullsafety.ParametersNotNullByDefault;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
@@ -129,7 +128,7 @@ public class ForumActivity extends
private void showUnsubscribeDialog() { private void showUnsubscribeDialog() {
OnClickListener okListener = (dialog, which) -> viewModel.deleteForum(); OnClickListener okListener = (dialog, which) -> viewModel.deleteForum();
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this, AlertDialog.Builder builder = new AlertDialog.Builder(this,
R.style.BriarDialogTheme); R.style.BriarDialogTheme);
builder.setTitle(getString(R.string.dialog_title_leave_forum)); builder.setTitle(getString(R.string.dialog_title_leave_forum));
builder.setMessage(getString(R.string.dialog_message_leave_forum)); builder.setMessage(getString(R.string.dialog_message_leave_forum));

View File

@@ -13,18 +13,15 @@ import androidx.recyclerview.widget.ListAdapter;
@NotNullByDefault @NotNullByDefault
class ForumListAdapter extends ListAdapter<ForumListItem, ForumViewHolder> { class ForumListAdapter extends ListAdapter<ForumListItem, ForumViewHolder> {
private final ForumListViewModel viewModel; ForumListAdapter() {
ForumListAdapter(ForumListViewModel viewModel) {
super(new ForumListCallback()); super(new ForumListCallback());
this.viewModel = viewModel;
} }
@Override @Override
public ForumViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { public ForumViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate( View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.list_item_forum, parent, false); R.layout.list_item_forum, parent, false);
return new ForumViewHolder(v, viewModel); return new ForumViewHolder(v);
} }
@Override @Override

View File

@@ -40,7 +40,7 @@ public class ForumListFragment extends BaseFragment implements
private ForumListViewModel viewModel; private ForumListViewModel viewModel;
private BriarRecyclerView list; private BriarRecyclerView list;
private Snackbar snackbar; private Snackbar snackbar;
private ForumListAdapter adapter; private final ForumListAdapter adapter = new ForumListAdapter();
@Inject @Inject
ViewModelProvider.Factory viewModelFactory; ViewModelProvider.Factory viewModelFactory;
@@ -54,7 +54,6 @@ public class ForumListFragment extends BaseFragment implements
component.inject(this); component.inject(this);
viewModel = new ViewModelProvider(this, viewModelFactory) viewModel = new ViewModelProvider(this, viewModelFactory)
.get(ForumListViewModel.class); .get(ForumListViewModel.class);
adapter = new ForumListAdapter(viewModel);
} }
@Nullable @Nullable

View File

@@ -1,7 +1,6 @@
package org.briarproject.briar.android.forum; package org.briarproject.briar.android.forum;
import android.app.Application; import android.app.Application;
import android.widget.Toast;
import org.briarproject.bramble.api.contact.event.ContactRemovedEvent; import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
import org.briarproject.bramble.api.db.DatabaseExecutor; import org.briarproject.bramble.api.db.DatabaseExecutor;
@@ -16,7 +15,6 @@ import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.event.GroupAddedEvent; import org.briarproject.bramble.api.sync.event.GroupAddedEvent;
import org.briarproject.bramble.api.sync.event.GroupRemovedEvent; import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.briar.R;
import org.briarproject.briar.android.viewmodel.DbViewModel; import org.briarproject.briar.android.viewmodel.DbViewModel;
import org.briarproject.briar.android.viewmodel.LiveResult; import org.briarproject.briar.android.viewmodel.LiveResult;
import org.briarproject.briar.api.android.AndroidNotificationManager; import org.briarproject.briar.api.android.AndroidNotificationManager;
@@ -42,7 +40,6 @@ import androidx.annotation.UiThread;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import static android.widget.Toast.LENGTH_SHORT;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logDuration; import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.now; import static org.briarproject.bramble.util.LogUtils.now;
@@ -183,17 +180,4 @@ class ForumListViewModel extends DbViewModel implements EventListener {
return numInvitations; return numInvitations;
} }
void deleteForum(GroupId groupId) {
runOnDbThread(() -> {
try {
Forum f = forumManager.getForum(groupId);
forumManager.removeForum(f);
androidExecutor.runOnUiThread(() -> Toast
.makeText(getApplication(), R.string.forum_left_toast,
LENGTH_SHORT).show());
} catch (DbException e) {
handleException(e);
}
});
}
} }

View File

@@ -4,7 +4,6 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.PopupMenu;
import android.widget.TextView; import android.widget.TextView;
import org.briarproject.briar.R; import org.briarproject.briar.R;
@@ -21,7 +20,6 @@ import static org.briarproject.briar.android.activity.BriarActivity.GROUP_NAME;
class ForumViewHolder extends RecyclerView.ViewHolder { class ForumViewHolder extends RecyclerView.ViewHolder {
private final ForumListViewModel viewModel;
private final Context ctx; private final Context ctx;
private final ViewGroup layout; private final ViewGroup layout;
private final TextAvatarView avatar; private final TextAvatarView avatar;
@@ -29,9 +27,8 @@ class ForumViewHolder extends RecyclerView.ViewHolder {
private final TextView postCount; private final TextView postCount;
private final TextView date; private final TextView date;
ForumViewHolder(View v, ForumListViewModel viewModel) { ForumViewHolder(View v) {
super(v); super(v);
this.viewModel = viewModel;
ctx = v.getContext(); ctx = v.getContext();
layout = (ViewGroup) v; layout = (ViewGroup) v;
avatar = v.findViewById(R.id.avatarView); avatar = v.findViewById(R.id.avatarView);
@@ -67,21 +64,6 @@ class ForumViewHolder extends RecyclerView.ViewHolder {
date.setVisibility(VISIBLE); date.setVisibility(VISIBLE);
} }
// Open popup menu on long click
layout.setOnLongClickListener(v -> {
PopupMenu pm = new PopupMenu(ctx, v);
pm.getMenuInflater().inflate(R.menu.forum_list_item_actions,
pm.getMenu());
pm.setOnMenuItemClickListener(it -> {
if (it.getItemId() == R.id.action_forum_delete) {
viewModel.deleteForum(item.getForum().getId());
}
return true;
});
pm.show();
return true;
});
// Open Forum on Click // Open Forum on Click
layout.setOnClickListener(v -> { layout.setOnClickListener(v -> {
Intent i = new Intent(ctx, ForumActivity.class); Intent i = new Intent(ctx, ForumActivity.class);

View File

@@ -13,8 +13,6 @@ import android.view.View;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.TextView; import android.widget.TextView;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.BaseActivity; import org.briarproject.briar.android.activity.BaseActivity;
import org.briarproject.briar.api.android.ScreenFilterMonitor; import org.briarproject.briar.api.android.ScreenFilterMonitor;
@@ -29,6 +27,7 @@ import java.util.Collection;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment; import androidx.fragment.app.DialogFragment;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
@@ -76,8 +75,8 @@ public class ScreenFilterDialogFragment extends DialogFragment {
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
Activity activity = getActivity(); Activity activity = getActivity();
if (activity == null) throw new IllegalStateException(); if (activity == null) throw new IllegalStateException();
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder( AlertDialog.Builder builder = new AlertDialog.Builder(activity,
activity, R.style.BriarDialogThemeNoFilter); R.style.BriarDialogThemeNoFilter);
builder.setTitle(R.string.screen_filter_title); builder.setTitle(R.string.screen_filter_title);
Bundle args = getArguments(); Bundle args = getArguments();
if (args == null) throw new IllegalStateException(); if (args == null) throw new IllegalStateException();

View File

@@ -6,13 +6,12 @@ import android.content.Intent;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.widget.Toast; import android.widget.Toast;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.appcompat.app.AlertDialog;
import androidx.core.util.Consumer; import androidx.core.util.Consumer;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
@@ -74,8 +73,7 @@ abstract class AbstractConditionManager {
void showRationale(Context ctx, @StringRes int title, void showRationale(Context ctx, @StringRes int title,
@StringRes int body, Runnable onContinueClicked, @StringRes int body, Runnable onContinueClicked,
Runnable onDismiss) { Runnable onDismiss) {
MaterialAlertDialogBuilder builder = AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
new MaterialAlertDialogBuilder(ctx);
builder.setTitle(title); builder.setTitle(title);
builder.setMessage(body); builder.setMessage(body);
builder.setNeutralButton(R.string.continue_button, builder.setNeutralButton(R.string.continue_button,

View File

@@ -61,7 +61,6 @@ public class HotspotIntroFragment extends Fragment {
getAndroidComponent(activity).inject(this); getAndroidComponent(activity).inject(this);
viewModel = new ViewModelProvider(activity, viewModelFactory) viewModel = new ViewModelProvider(activity, viewModelFactory)
.get(HotspotViewModel.class); .get(HotspotViewModel.class);
conditionManager.init(requireActivity());
} }
@Override @Override
@@ -77,6 +76,8 @@ public class HotspotIntroFragment extends Fragment {
startButton.setOnClickListener(this::onButtonClick); startButton.setOnClickListener(this::onButtonClick);
conditionManager.init(requireActivity());
return v; return v;
} }

View File

@@ -432,8 +432,7 @@ class HotspotManager {
@RequiresApi(29) @RequiresApi(29)
private String getPassword() { private String getPassword() {
return getRandomString(4) + "-" + getRandomString(4) + "-" + return getRandomString(8);
getRandomString(4) + "-" + getRandomString(4);
} }
private static String createWifiLoginString(String ssid, String password) { private static String createWifiLoginString(String ssid, String password) {

View File

@@ -32,7 +32,6 @@ import static android.widget.Toast.LENGTH_LONG;
import static org.briarproject.bramble.api.crypto.DecryptionResult.KEY_STRENGTHENER_ERROR; import static org.briarproject.bramble.api.crypto.DecryptionResult.KEY_STRENGTHENER_ERROR;
import static org.briarproject.bramble.api.crypto.DecryptionResult.SUCCESS; import static org.briarproject.bramble.api.crypto.DecryptionResult.SUCCESS;
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK; import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.STRONG;
import static org.briarproject.briar.android.login.LoginUtils.createKeyStrengthenerErrorDialog; import static org.briarproject.briar.android.login.LoginUtils.createKeyStrengthenerErrorDialog;
import static org.briarproject.briar.android.util.UiUtils.hideSoftKeyboard; import static org.briarproject.briar.android.util.UiUtils.hideSoftKeyboard;
import static org.briarproject.briar.android.util.UiUtils.setError; import static org.briarproject.briar.android.util.UiUtils.setError;
@@ -124,25 +123,12 @@ public class ChangePasswordActivity extends BriarActivity
boolean passwordsMatch = firstPassword.equals(secondPassword); boolean passwordsMatch = firstPassword.equals(secondPassword);
float strength = viewModel.estimatePasswordStrength(firstPassword); float strength = viewModel.estimatePasswordStrength(firstPassword);
strengthMeter.setStrength(strength); strengthMeter.setStrength(strength);
if (!firstPassword.isEmpty()) {
if (strength >= STRONG) {
newPasswordEntryWrapper.setHelperText(
getString(R.string.password_strong));
} else if (strength >= QUITE_WEAK) {
newPasswordEntryWrapper.setHelperText(
getString(R.string.password_quite_strong));
} else {
newPasswordEntryWrapper.setHelperTextEnabled(false);
}
}
setError(newPasswordEntryWrapper, setError(newPasswordEntryWrapper,
getString(R.string.password_too_weak), getString(R.string.password_too_weak),
!firstPassword.isEmpty() && strength < QUITE_WEAK); firstPassword.length() > 0 && strength < QUITE_WEAK);
setError(newPasswordConfirmationWrapper, setError(newPasswordConfirmationWrapper,
getString(R.string.passwords_do_not_match), getString(R.string.passwords_do_not_match),
!secondPassword.isEmpty() && !passwordsMatch); secondPassword.length() > 0 && !passwordsMatch);
changePasswordButton.setEnabled( changePasswordButton.setEnabled(
!currentPassword.getText().toString().isEmpty() && !currentPassword.getText().toString().isEmpty() &&
passwordsMatch && strength >= QUITE_WEAK); passwordsMatch && strength >= QUITE_WEAK);

View File

@@ -2,8 +2,6 @@ package org.briarproject.briar.android.login;
import android.content.Context; import android.content.Context;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.nullsafety.NotNullByDefault; import org.briarproject.nullsafety.NotNullByDefault;
@@ -15,8 +13,8 @@ import static org.briarproject.briar.android.util.UiUtils.getDialogIcon;
class LoginUtils { class LoginUtils {
static AlertDialog createKeyStrengthenerErrorDialog(Context ctx) { static AlertDialog createKeyStrengthenerErrorDialog(Context ctx) {
MaterialAlertDialogBuilder builder = AlertDialog.Builder builder =
new MaterialAlertDialogBuilder(ctx, R.style.BriarDialogTheme); new AlertDialog.Builder(ctx, R.style.BriarDialogTheme);
builder.setIcon(getDialogIcon(ctx, R.drawable.alerts_and_states_error)); builder.setIcon(getDialogIcon(ctx, R.drawable.alerts_and_states_error));
builder.setTitle(R.string.dialog_title_cannot_check_password); builder.setTitle(R.string.dialog_title_cannot_check_password);
builder.setMessage(R.string.dialog_message_cannot_check_password); builder.setMessage(R.string.dialog_message_cannot_check_password);

View File

@@ -9,7 +9,6 @@ import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout; import com.google.android.material.textfield.TextInputLayout;
@@ -41,7 +40,6 @@ import static org.briarproject.bramble.api.crypto.DecryptionResult.SUCCESS;
import static org.briarproject.briar.android.login.LoginUtils.createKeyStrengthenerErrorDialog; import static org.briarproject.briar.android.login.LoginUtils.createKeyStrengthenerErrorDialog;
import static org.briarproject.briar.android.util.UiUtils.enterPressed; import static org.briarproject.briar.android.util.UiUtils.enterPressed;
import static org.briarproject.briar.android.util.UiUtils.hideSoftKeyboard; import static org.briarproject.briar.android.util.UiUtils.hideSoftKeyboard;
import static org.briarproject.briar.android.util.UiUtils.hideViewOnSmallScreen;
import static org.briarproject.briar.android.util.UiUtils.setError; import static org.briarproject.briar.android.util.UiUtils.setError;
import static org.briarproject.briar.android.util.UiUtils.showSoftKeyboard; import static org.briarproject.briar.android.util.UiUtils.showSoftKeyboard;
@@ -102,12 +100,6 @@ public class PasswordFragment extends BaseFragment implements TextWatcher {
return v; return v;
} }
@Override
public void onStart() {
super.onStart();
hideViewOnSmallScreen(requireView().findViewById(R.id.logo));
}
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, public void beforeTextChanged(CharSequence s, int start, int count,
int after) { int after) {
@@ -155,11 +147,9 @@ public class PasswordFragment extends BaseFragment implements TextWatcher {
} }
private void onForgottenPasswordClick() { private void onForgottenPasswordClick() {
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder( AlertDialog.Builder builder = new AlertDialog.Builder(requireContext(),
requireContext(), R.style.BriarDialogTheme); R.style.BriarDialogTheme);
builder.setTitle(R.string.dialog_title_lost_password); builder.setTitle(R.string.dialog_title_lost_password);
builder.setBackgroundInsetStart(25);
builder.setBackgroundInsetEnd(25);
builder.setMessage(R.string.dialog_message_lost_password); builder.setMessage(R.string.dialog_message_lost_password);
builder.setPositiveButton(R.string.cancel, null); builder.setPositiveButton(R.string.cancel, null);
builder.setNegativeButton(R.string.delete, builder.setNegativeButton(R.string.delete,

View File

@@ -1,6 +1,5 @@
package org.briarproject.briar.android.login; package org.briarproject.briar.android.login;
import android.annotation.SuppressLint;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
@@ -75,7 +74,6 @@ public class StartupActivity extends BaseActivity implements
} }
@Override @Override
@SuppressLint("MissingSuperCall")
public void onBackPressed() { public void onBackPressed() {
// Move task and activity to the background instead of showing another // Move task and activity to the background instead of showing another
// password prompt. // password prompt.

View File

@@ -11,7 +11,6 @@ import android.widget.RadioGroup;
import android.widget.ScrollView; import android.widget.ScrollView;
import com.google.android.material.animation.ArgbEvaluatorCompat; import com.google.android.material.animation.ArgbEvaluatorCompat;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.view.BriarButton; import org.briarproject.briar.android.view.BriarButton;
@@ -25,6 +24,7 @@ import javax.inject.Inject;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
@@ -148,8 +148,8 @@ public class ErrorWizardFragment extends Fragment {
} }
private void onUnlinkButtonClicked(View v) { private void onUnlinkButtonClicked(View v) {
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder( AlertDialog.Builder builder = new AlertDialog.Builder(requireContext(),
requireContext(), R.style.BriarDialogTheme); R.style.BriarDialogTheme);
builder.setTitle(R.string.mailbox_status_unlink_dialog_title); builder.setTitle(R.string.mailbox_status_unlink_dialog_title);
builder.setMessage(R.string.mailbox_status_unlink_dialog_question); builder.setMessage(R.string.mailbox_status_unlink_dialog_question);
builder.setPositiveButton(R.string.cancel, builder.setPositiveButton(R.string.cancel,

View File

@@ -5,8 +5,6 @@ import android.view.MenuItem;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.Toast; import android.widget.Toast;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.bramble.api.mailbox.MailboxPairingState; import org.briarproject.bramble.api.mailbox.MailboxPairingState;
import org.briarproject.bramble.api.mailbox.MailboxPairingState.ConnectionError; import org.briarproject.bramble.api.mailbox.MailboxPairingState.ConnectionError;
import org.briarproject.bramble.api.mailbox.MailboxPairingState.InvalidQrCode; import org.briarproject.bramble.api.mailbox.MailboxPairingState.InvalidQrCode;
@@ -33,6 +31,7 @@ import org.briarproject.nullsafety.ParametersNotNullByDefault;
import javax.inject.Inject; import javax.inject.Inject;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
@@ -250,8 +249,8 @@ public class MailboxActivity extends BriarActivity {
if (tellUserToWipeMailbox) { if (tellUserToWipeMailbox) {
showFragment(getSupportFragmentManager(), new BlankFragment(), showFragment(getSupportFragmentManager(), new BlankFragment(),
BlankFragment.TAG); BlankFragment.TAG);
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder( AlertDialog.Builder builder =
this, R.style.BriarDialogTheme); new AlertDialog.Builder(this, R.style.BriarDialogTheme);
builder.setTitle(R.string.mailbox_status_unlink_no_wipe_title); builder.setTitle(R.string.mailbox_status_unlink_no_wipe_title);
builder.setMessage(R.string.mailbox_status_unlink_no_wipe_message); builder.setMessage(R.string.mailbox_status_unlink_no_wipe_message);
builder.setNeutralButton(R.string.got_it, builder.setNeutralButton(R.string.got_it,

View File

@@ -13,8 +13,6 @@ import android.widget.ImageView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.bramble.api.mailbox.MailboxStatus; import org.briarproject.bramble.api.mailbox.MailboxStatus;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.view.BriarButton; import org.briarproject.briar.android.view.BriarButton;
@@ -216,8 +214,8 @@ public class MailboxStatusFragment extends Fragment {
} }
private void onUnlinkButtonClicked(boolean showWarning) { private void onUnlinkButtonClicked(boolean showWarning) {
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder( AlertDialog.Builder builder = new AlertDialog.Builder(requireContext(),
requireContext(), R.style.BriarDialogTheme); R.style.BriarDialogTheme);
builder.setTitle(R.string.mailbox_status_unlink_dialog_title); builder.setTitle(R.string.mailbox_status_unlink_dialog_title);
String msg = getString(R.string.mailbox_status_unlink_dialog_question); String msg = getString(R.string.mailbox_status_unlink_dialog_question);
if (showWarning) { if (showWarning) {

View File

@@ -48,7 +48,6 @@ import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.plugin.Plugin.PREF_PLUGIN_ENABLE; import static org.briarproject.bramble.api.plugin.Plugin.PREF_PLUGIN_ENABLE;
import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING; import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING;
import static org.briarproject.bramble.util.AndroidUtils.registerReceiver;
import static org.briarproject.bramble.util.LogUtils.logDuration; import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.now; import static org.briarproject.bramble.util.LogUtils.now;
@@ -97,7 +96,7 @@ public class PluginViewModel extends DbViewModel implements EventListener {
this.eventBus = eventBus; this.eventBus = eventBus;
eventBus.addListener(this); eventBus.addListener(this);
receiver = new BluetoothStateReceiver(); receiver = new BluetoothStateReceiver();
registerReceiver(app, receiver, new IntentFilter(ACTION_STATE_CHANGED)); app.registerReceiver(receiver, new IntentFilter(ACTION_STATE_CHANGED));
networkStatus.setValue(networkManager.getNetworkStatus()); networkStatus.setValue(networkManager.getNetworkStatus());
torPluginState.setValue(getTransportState(TorConstants.ID)); torPluginState.setValue(getTransportState(TorConstants.ID));
wifiPluginState.setValue(getTransportState(LanTcpConstants.ID)); wifiPluginState.setValue(getTransportState(LanTcpConstants.ID));

View File

@@ -219,8 +219,7 @@ public class TransportsActivity extends BriarActivity {
} }
private void onClicked(TransportId transportId, boolean enable) { private void onClicked(TransportId transportId, boolean enable) {
if (transportId.equals(BluetoothConstants.ID) && enable if (enable && SDK_INT >= 31 && !areBluetoothPermissionsGranted(this)) {
&& SDK_INT >= 31 && !areBluetoothPermissionsGranted(this)) {
if (shouldShowRequestPermissionRationale(BLUETOOTH_CONNECT)) { if (shouldShowRequestPermissionRationale(BLUETOOTH_CONNECT)) {
showRationale(this, R.string.permission_bluetooth_title, showRationale(this, R.string.permission_bluetooth_title,
R.string.permission_bluetooth_body, R.string.permission_bluetooth_body,

View File

@@ -10,8 +10,6 @@ import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import java.util.ArrayList; import java.util.ArrayList;
@@ -19,6 +17,7 @@ import java.util.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.ListPreference; import androidx.preference.ListPreference;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.SwitchPreferenceCompat; import androidx.preference.SwitchPreferenceCompat;
@@ -202,8 +201,8 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
getActivity().finish(); getActivity().finish();
}; };
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder( AlertDialog.Builder builder = new AlertDialog.Builder(getContext(),
requireContext(), R.style.BriarDialogTheme); R.style.BriarDialogTheme);
builder.setTitle(getString(R.string.dialog_title_connect_panic_app)); builder.setTitle(getString(R.string.dialog_title_connect_panic_app));
CharSequence app = getString(R.string.unknown_app); CharSequence app = getString(R.string.unknown_app);

View File

@@ -6,8 +6,6 @@ import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.privategroup.creation.GroupInviteActivity; import org.briarproject.briar.android.privategroup.creation.GroupInviteActivity;
@@ -22,6 +20,7 @@ import org.briarproject.nullsafety.ParametersNotNullByDefault;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
@@ -179,8 +178,8 @@ public class GroupActivity extends
} }
private void showLeaveGroupDialog() { private void showLeaveGroupDialog() {
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder( AlertDialog.Builder builder =
this, R.style.BriarDialogTheme); new AlertDialog.Builder(this, R.style.BriarDialogTheme);
builder.setTitle(getString(R.string.groups_leave_dialog_title)); builder.setTitle(getString(R.string.groups_leave_dialog_title));
builder.setMessage(getString(R.string.groups_leave_dialog_message)); builder.setMessage(getString(R.string.groups_leave_dialog_message));
builder.setNegativeButton(R.string.dialog_button_leave, builder.setNegativeButton(R.string.dialog_button_leave,
@@ -190,8 +189,8 @@ public class GroupActivity extends
} }
private void showDissolveGroupDialog() { private void showDissolveGroupDialog() {
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder( AlertDialog.Builder builder =
this, R.style.BriarDialogTheme); new AlertDialog.Builder(this, R.style.BriarDialogTheme);
builder.setTitle(getString(R.string.groups_dissolve_dialog_title)); builder.setTitle(getString(R.string.groups_dissolve_dialog_title));
builder.setMessage(getString(R.string.groups_dissolve_dialog_message)); builder.setMessage(getString(R.string.groups_dissolve_dialog_message));
builder.setNegativeButton(R.string.groups_dissolve_button, builder.setNegativeButton(R.string.groups_dissolve_button,
@@ -207,8 +206,8 @@ public class GroupActivity extends
} }
private void onGroupDissolved() { private void onGroupDissolved() {
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder( AlertDialog.Builder builder =
this, R.style.BriarDialogTheme); new AlertDialog.Builder(this, R.style.BriarDialogTheme);
builder.setTitle(getString(R.string.groups_dissolved_dialog_title)); builder.setTitle(getString(R.string.groups_dissolved_dialog_title));
builder.setMessage(getString(R.string.groups_dissolved_dialog_message)); builder.setMessage(getString(R.string.groups_dissolved_dialog_message));
builder.setNeutralButton(R.string.ok, null); builder.setNeutralButton(R.string.ok, null);

View File

@@ -9,8 +9,6 @@ import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.widget.Button; import android.widget.Button;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
@@ -28,6 +26,7 @@ import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import androidx.annotation.LayoutRes; import androidx.annotation.LayoutRes;
import androidx.appcompat.app.AlertDialog;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
@@ -106,8 +105,7 @@ public class RevealContactsActivity extends ContactSelectorActivity
} }
private void showOnboardingDialog() { private void showOnboardingDialog() {
new MaterialAlertDialogBuilder(this, new AlertDialog.Builder(this, R.style.OnboardingDialogTheme)
R.style.OnboardingDialogTheme)
.setMessage(getString(R.string.groups_reveal_dialog_message)) .setMessage(getString(R.string.groups_reveal_dialog_message))
.setNeutralButton(R.string.got_it, .setNeutralButton(R.string.got_it,
(dialog, which) -> dialog.cancel()) (dialog, which) -> dialog.cancel())

View File

@@ -1,6 +1,5 @@
package org.briarproject.briar.android.reporting; package org.briarproject.briar.android.reporting;
import android.annotation.SuppressLint;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
@@ -88,7 +87,6 @@ public class CrashReportActivity extends BaseActivity
} }
@Override @Override
@SuppressLint("MissingSuperCall")
public void onBackPressed() { public void onBackPressed() {
exit(); exit();
} }

View File

@@ -10,7 +10,6 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.BaseActivity; import org.briarproject.briar.android.activity.BaseActivity;
@@ -21,6 +20,7 @@ import org.briarproject.nullsafety.ParametersNotNullByDefault;
import javax.inject.Inject; import javax.inject.Inject;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment; import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
@@ -86,7 +86,7 @@ public class ConfirmAvatarDialogFragment extends DialogFragment {
); );
int theme = R.style.BriarDialogTheme; int theme = R.style.BriarDialogTheme;
return new MaterialAlertDialogBuilder(activity, theme) return new AlertDialog.Builder(activity, theme)
.setView(view) .setView(view)
.setTitle(R.string.dialog_confirm_profile_picture_title) .setTitle(R.string.dialog_confirm_profile_picture_title)
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)

View File

@@ -1,19 +1,21 @@
package org.briarproject.briar.android.settings; package org.briarproject.briar.android.settings;
import android.app.AlertDialog;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.Localizer; import org.briarproject.briar.android.Localizer;
import org.briarproject.briar.android.util.UiUtils; import org.briarproject.briar.android.util.UiUtils;
import org.briarproject.nullsafety.NotNullByDefault; import org.briarproject.nullsafety.NotNullByDefault;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.logging.Logger;
import androidx.core.text.TextUtilsCompat;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import androidx.preference.ListPreference; import androidx.preference.ListPreference;
import androidx.preference.Preference; import androidx.preference.Preference;
@@ -22,7 +24,10 @@ import androidx.preference.PreferenceFragmentCompat;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.os.Build.VERSION.SDK_INT;
import static androidx.core.view.ViewCompat.LAYOUT_DIRECTION_LTR;
import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNull;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.briar.android.BriarApplication.ENTRY_ACTIVITY; import static org.briarproject.briar.android.BriarApplication.ENTRY_ACTIVITY;
import static org.briarproject.briar.android.navdrawer.NavDrawerActivity.SIGN_OUT_URI; import static org.briarproject.briar.android.navdrawer.NavDrawerActivity.SIGN_OUT_URI;
import static org.briarproject.briar.android.settings.SettingsActivity.EXTRA_THEME_CHANGE; import static org.briarproject.briar.android.settings.SettingsActivity.EXTRA_THEME_CHANGE;
@@ -31,7 +36,10 @@ import static org.briarproject.briar.android.settings.SettingsActivity.EXTRA_THE
public class DisplayFragment extends PreferenceFragmentCompat { public class DisplayFragment extends PreferenceFragmentCompat {
public static final String PREF_LANGUAGE = "pref_key_language"; public static final String PREF_LANGUAGE = "pref_key_language";
public static final String PREF_THEME = "pref_key_theme"; private static final String PREF_THEME = "pref_key_theme";
private static final Logger LOG =
getLogger(DisplayFragment.class.getName());
@Override @Override
public void onCreatePreferences(Bundle bundle, String s) { public void onCreatePreferences(Bundle bundle, String s) {
@@ -42,6 +50,7 @@ public class DisplayFragment extends PreferenceFragmentCompat {
language.setOnPreferenceChangeListener(this::onLanguageChanged); language.setOnPreferenceChangeListener(this::onLanguageChanged);
ListPreference theme = requireNonNull(findPreference(PREF_THEME)); ListPreference theme = requireNonNull(findPreference(PREF_THEME));
setThemeEntries(theme);
theme.setOnPreferenceChangeListener(this::onThemeChanged); theme.setOnPreferenceChangeListener(this::onThemeChanged);
} }
@@ -82,6 +91,30 @@ public class DisplayFragment extends PreferenceFragmentCompat {
language.setEntryValues(entryValues.toArray(new CharSequence[0])); language.setEntryValues(entryValues.toArray(new CharSequence[0]));
} }
private boolean isLeftToRight(Locale locale) {
// TextUtilsCompat returns the wrong direction for Hebrew on some phones
String language = locale.getLanguage();
if (language.equals("iw") || language.equals("he")) return false;
int direction = TextUtilsCompat.getLayoutDirectionFromLocale(locale);
return direction == LAYOUT_DIRECTION_LTR;
}
private void setThemeEntries(ListPreference theme) {
if (SDK_INT < 27) {
// remove System Default Theme option from preference entries
// as it is not functional on this API anyway
List<CharSequence> entries =
new ArrayList<>(Arrays.asList(theme.getEntries()));
entries.remove(getString(R.string.pref_theme_system));
theme.setEntries(entries.toArray(new CharSequence[0]));
// also remove corresponding value
List<CharSequence> values =
new ArrayList<>(Arrays.asList(theme.getEntryValues()));
values.remove(getString(R.string.pref_theme_system_value));
theme.setEntryValues(values.toArray(new CharSequence[0]));
}
}
private boolean onThemeChanged(Preference preference, Object newValue) { private boolean onThemeChanged(Preference preference, Object newValue) {
// activate new theme // activate new theme
FragmentActivity activity = requireActivity(); FragmentActivity activity = requireActivity();
@@ -102,8 +135,8 @@ public class DisplayFragment extends PreferenceFragmentCompat {
private boolean onLanguageChanged(Preference preference, Object newValue) { private boolean onLanguageChanged(Preference preference, Object newValue) {
ListPreference language = (ListPreference) preference; ListPreference language = (ListPreference) preference;
if (!language.getValue().equals(newValue)) { if (!language.getValue().equals(newValue)) {
MaterialAlertDialogBuilder builder = AlertDialog.Builder builder =
new MaterialAlertDialogBuilder(requireContext()); new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.pref_language_title); builder.setTitle(R.string.pref_language_title);
builder.setMessage(R.string.pref_language_changed); builder.setMessage(R.string.pref_language_changed);
builder.setPositiveButton(R.string.sign_out_button, (d, i) -> { builder.setPositiveButton(R.string.sign_out_button, (d, i) -> {

View File

@@ -40,12 +40,15 @@ class TorSummaryProvider implements SummaryProvider<ListPreference> {
String country = locationUtils.getCurrentCountry(); String country = locationUtils.getCurrentCountry();
String countryName = getCountryDisplayName(country); String countryName = getCountryDisplayName(country);
boolean useBridgesByDefault = boolean blocked =
circumventionProvider.shouldUseBridges(country); circumventionProvider.isTorProbablyBlocked(country);
boolean useBridges = circumventionProvider.doBridgesWork(country);
String setting = String setting =
ctx.getString(R.string.tor_network_setting_without_bridges); ctx.getString(R.string.tor_network_setting_without_bridges);
if (useBridgesByDefault) { if (blocked && useBridges) {
setting = ctx.getString(R.string.tor_network_setting_with_bridges); setting = ctx.getString(R.string.tor_network_setting_with_bridges);
} else if (blocked) {
setting = ctx.getString(R.string.tor_network_setting_never);
} }
return ctx.getString(R.string.tor_network_setting_summary, setting, return ctx.getString(R.string.tor_network_setting_summary, setting,
countryName); countryName);

View File

@@ -13,7 +13,6 @@ import org.briarproject.briar.android.Localizer;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import static android.content.Intent.ACTION_VIEW; import static android.content.Intent.ACTION_VIEW;
import static android.os.Build.VERSION.SDK_INT;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE; import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static org.briarproject.briar.android.TestingConstants.PREVENT_SCREENSHOTS; import static org.briarproject.briar.android.TestingConstants.PREVENT_SCREENSHOTS;
@@ -26,8 +25,6 @@ public class ExpiredActivity extends AppCompatActivity
if (PREVENT_SCREENSHOTS) getWindow().addFlags(FLAG_SECURE); if (PREVENT_SCREENSHOTS) getWindow().addFlags(FLAG_SECURE);
if (SDK_INT >= 31) getWindow().setHideOverlayWindows(true);
setContentView(R.layout.activity_expired); setContentView(R.layout.activity_expired);
findViewById(R.id.download_briar_button).setOnClickListener(this); findViewById(R.id.download_briar_button).setOnClickListener(this);
} }
@@ -41,7 +38,7 @@ public class ExpiredActivity extends AppCompatActivity
@Override @Override
public void onClick(View v) { public void onClick(View v) {
Uri uri = Uri.parse("https://briarproject.org/download-briar"); Uri uri = Uri.parse("https://briarproject.org/download.html");
startActivity(new Intent(ACTION_VIEW, uri)); startActivity(new Intent(ACTION_VIEW, uri));
finish(); finish();
} }

View File

@@ -18,8 +18,7 @@ import static androidx.core.content.ContextCompat.getColor;
public class BriarSnackbarBuilder { public class BriarSnackbarBuilder {
@ColorRes @ColorRes
@Nullable private int backgroundResId = R.color.briar_primary;
private Integer backgroundResId = null;
@StringRes @StringRes
private int actionResId; private int actionResId;
@Nullable @Nullable
@@ -27,11 +26,7 @@ public class BriarSnackbarBuilder {
public Snackbar make(View view, CharSequence text, int duration) { public Snackbar make(View view, CharSequence text, int duration) {
Snackbar s = Snackbar.make(view, text, duration); Snackbar s = Snackbar.make(view, text, duration);
if (backgroundResId != null) { s.getView().setBackgroundResource(backgroundResId);
s.setBackgroundTint(getColor(view.getContext(), backgroundResId));
s.setTextColor(
getColor(view.getContext(), R.color.md_theme_onSecondary));
}
if (onClickListener != null) { if (onClickListener != null) {
s.setActionTextColor(getColor(view.getContext(), s.setActionTextColor(getColor(view.getContext(),
R.color.briar_button_text_positive)); R.color.briar_button_text_positive));

Some files were not shown because too many files have changed in this diff Show More