mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-16 20:59:54 +01:00
Compare commits
6 Commits
tor-probe
...
screenshot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d5f5d4419 | ||
|
|
8393513871 | ||
|
|
38270fbee8 | ||
|
|
65c0646812 | ||
|
|
0416583e8c | ||
|
|
91f8c801b8 |
9
.idea/codeStyles/Project.xml
generated
9
.idea/codeStyles/Project.xml
generated
@@ -36,9 +36,6 @@
|
|||||||
<option name="JD_ALIGN_PARAM_COMMENTS" value="false" />
|
<option name="JD_ALIGN_PARAM_COMMENTS" value="false" />
|
||||||
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false" />
|
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false" />
|
||||||
</JavaCodeStyleSettings>
|
</JavaCodeStyleSettings>
|
||||||
<JetCodeStyleSettings>
|
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
|
||||||
</JetCodeStyleSettings>
|
|
||||||
<Objective-C-extensions>
|
<Objective-C-extensions>
|
||||||
<file>
|
<file>
|
||||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
|
||||||
@@ -260,11 +257,5 @@
|
|||||||
</rules>
|
</rules>
|
||||||
</arrangement>
|
</arrangement>
|
||||||
</codeStyleSettings>
|
</codeStyleSettings>
|
||||||
<codeStyleSettings language="kotlin">
|
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
|
||||||
<option name="PARAMETER_ANNOTATION_WRAP" value="1" />
|
|
||||||
<option name="VARIABLE_ANNOTATION_WRAP" value="1" />
|
|
||||||
<option name="ENUM_CONSTANTS_WRAP" value="1" />
|
|
||||||
</codeStyleSettings>
|
|
||||||
</code_scheme>
|
</code_scheme>
|
||||||
</component>
|
</component>
|
||||||
20
.idea/runConfigurations/All_in_briar_headless.xml
generated
20
.idea/runConfigurations/All_in_briar_headless.xml
generated
@@ -1,20 +0,0 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
|
||||||
<configuration default="false" name="All in briar-headless" type="AndroidJUnit" factoryName="Android JUnit" nameIsGenerated="true">
|
|
||||||
<module name="briar-headless" />
|
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
|
||||||
<option name="PACKAGE_NAME" value="" />
|
|
||||||
<option name="MAIN_CLASS_NAME" value="" />
|
|
||||||
<option name="METHOD_NAME" value="" />
|
|
||||||
<option name="TEST_OBJECT" value="package" />
|
|
||||||
<option name="VM_PARAMETERS" value="" />
|
|
||||||
<option name="PARAMETERS" value="" />
|
|
||||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-headless" />
|
|
||||||
<option name="PASS_PARENT_ENVS" value="true" />
|
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
|
||||||
<value defaultName="singleModule" />
|
|
||||||
</option>
|
|
||||||
<patterns />
|
|
||||||
<method />
|
|
||||||
</configuration>
|
|
||||||
</component>
|
|
||||||
3
.idea/runConfigurations/All_tests.xml
generated
3
.idea/runConfigurations/All_tests.xml
generated
@@ -24,7 +24,6 @@
|
|||||||
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-android" run_configuration_type="AndroidJUnit" />
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-android" run_configuration_type="AndroidJUnit" />
|
||||||
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-java" run_configuration_type="AndroidJUnit" />
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-java" run_configuration_type="AndroidJUnit" />
|
||||||
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-core" run_configuration_type="AndroidJUnit" />
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-core" run_configuration_type="AndroidJUnit" />
|
||||||
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All in briar-headless" run_configuration_type="AndroidJUnit" />
|
|
||||||
</method>
|
</method>
|
||||||
</configuration>
|
</configuration>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="All tests in bramble-android" type="AndroidJUnit" factoryName="Android JUnit">
|
<configuration default="false" name="All tests in bramble-android" type="AndroidJUnit" factoryName="Android JUnit">
|
||||||
|
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||||
<module name="bramble-android" />
|
<module name="bramble-android" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
@@ -10,10 +11,12 @@
|
|||||||
<option name="VM_PARAMETERS" value="-ea" />
|
<option name="VM_PARAMETERS" value="-ea" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-android" />
|
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-android" />
|
||||||
|
<option name="ENV_VARIABLES" />
|
||||||
<option name="PASS_PARENT_ENVS" value="true" />
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="singleModule" />
|
<value defaultName="singleModule" />
|
||||||
</option>
|
</option>
|
||||||
|
<envs />
|
||||||
<patterns />
|
<patterns />
|
||||||
<method />
|
<method />
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="All tests in bramble-api" type="AndroidJUnit" factoryName="Android JUnit">
|
<configuration default="false" name="All tests in bramble-api" type="AndroidJUnit" factoryName="Android JUnit">
|
||||||
|
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||||
<module name="bramble-api" />
|
<module name="bramble-api" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
@@ -10,10 +11,12 @@
|
|||||||
<option name="VM_PARAMETERS" value="-ea" />
|
<option name="VM_PARAMETERS" value="-ea" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-api" />
|
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-api" />
|
||||||
|
<option name="ENV_VARIABLES" />
|
||||||
<option name="PASS_PARENT_ENVS" value="true" />
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="singleModule" />
|
<value defaultName="singleModule" />
|
||||||
</option>
|
</option>
|
||||||
|
<envs />
|
||||||
<patterns />
|
<patterns />
|
||||||
<method />
|
<method />
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="All tests in bramble-core" type="AndroidJUnit" factoryName="Android JUnit">
|
<configuration default="false" name="All tests in bramble-core" type="AndroidJUnit" factoryName="Android JUnit">
|
||||||
|
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||||
<module name="bramble-core" />
|
<module name="bramble-core" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
@@ -10,10 +11,12 @@
|
|||||||
<option name="VM_PARAMETERS" value="-ea" />
|
<option name="VM_PARAMETERS" value="-ea" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-core" />
|
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-core" />
|
||||||
|
<option name="ENV_VARIABLES" />
|
||||||
<option name="PASS_PARENT_ENVS" value="true" />
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="singleModule" />
|
<value defaultName="singleModule" />
|
||||||
</option>
|
</option>
|
||||||
|
<envs />
|
||||||
<patterns />
|
<patterns />
|
||||||
<method />
|
<method />
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="All tests in bramble-java" type="AndroidJUnit" factoryName="Android JUnit">
|
<configuration default="false" name="All tests in bramble-java" type="AndroidJUnit" factoryName="Android JUnit">
|
||||||
|
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||||
<module name="bramble-java" />
|
<module name="bramble-java" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
@@ -10,10 +11,12 @@
|
|||||||
<option name="VM_PARAMETERS" value="-ea -Djava.library.path=libs" />
|
<option name="VM_PARAMETERS" value="-ea -Djava.library.path=libs" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-java" />
|
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-java" />
|
||||||
|
<option name="ENV_VARIABLES" />
|
||||||
<option name="PASS_PARENT_ENVS" value="true" />
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="singleModule" />
|
<value defaultName="singleModule" />
|
||||||
</option>
|
</option>
|
||||||
|
<envs />
|
||||||
<patterns />
|
<patterns />
|
||||||
<method />
|
<method />
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="All tests in briar-android" type="AndroidJUnit" factoryName="Android JUnit">
|
<configuration default="false" name="All tests in briar-android" type="AndroidJUnit" factoryName="Android JUnit">
|
||||||
|
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||||
<module name="briar-android" />
|
<module name="briar-android" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
@@ -10,10 +11,12 @@
|
|||||||
<option name="VM_PARAMETERS" value="-ea" />
|
<option name="VM_PARAMETERS" value="-ea" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-android" />
|
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-android" />
|
||||||
|
<option name="ENV_VARIABLES" />
|
||||||
<option name="PASS_PARENT_ENVS" value="true" />
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="singleModule" />
|
<value defaultName="singleModule" />
|
||||||
</option>
|
</option>
|
||||||
|
<envs />
|
||||||
<patterns />
|
<patterns />
|
||||||
<method />
|
<method />
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="All tests in briar-core" type="AndroidJUnit" factoryName="Android JUnit">
|
<configuration default="false" name="All tests in briar-core" type="AndroidJUnit" factoryName="Android JUnit">
|
||||||
|
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||||
<module name="briar-core" />
|
<module name="briar-core" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
@@ -10,10 +11,12 @@
|
|||||||
<option name="VM_PARAMETERS" value="-ea" />
|
<option name="VM_PARAMETERS" value="-ea" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-core" />
|
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-core" />
|
||||||
|
<option name="ENV_VARIABLES" />
|
||||||
<option name="PASS_PARENT_ENVS" value="true" />
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="singleModule" />
|
<value defaultName="singleModule" />
|
||||||
</option>
|
</option>
|
||||||
|
<envs />
|
||||||
<patterns />
|
<patterns />
|
||||||
<method />
|
<method />
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
3
.idea/runConfigurations/H2_Performance_Test.xml
generated
3
.idea/runConfigurations/H2_Performance_Test.xml
generated
@@ -1,5 +1,6 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="H2 Performance Test" type="AndroidJUnit" factoryName="Android JUnit">
|
<configuration default="false" name="H2 Performance Test" type="AndroidJUnit" factoryName="Android JUnit">
|
||||||
|
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||||
<module name="bramble-core" />
|
<module name="bramble-core" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
@@ -10,10 +11,12 @@
|
|||||||
<option name="VM_PARAMETERS" value="-ea" />
|
<option name="VM_PARAMETERS" value="-ea" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="" />
|
<option name="WORKING_DIRECTORY" value="" />
|
||||||
|
<option name="ENV_VARIABLES" />
|
||||||
<option name="PASS_PARENT_ENVS" value="true" />
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="singleModule" />
|
<value defaultName="singleModule" />
|
||||||
</option>
|
</option>
|
||||||
|
<envs />
|
||||||
<patterns />
|
<patterns />
|
||||||
<method />
|
<method />
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="HyperSQL Performance Test" type="AndroidJUnit" factoryName="Android JUnit">
|
<configuration default="false" name="HyperSQL Performance Test" type="AndroidJUnit" factoryName="Android JUnit">
|
||||||
|
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||||
<module name="bramble-core" />
|
<module name="bramble-core" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
@@ -10,10 +11,12 @@
|
|||||||
<option name="VM_PARAMETERS" value="-ea" />
|
<option name="VM_PARAMETERS" value="-ea" />
|
||||||
<option name="PARAMETERS" value="" />
|
<option name="PARAMETERS" value="" />
|
||||||
<option name="WORKING_DIRECTORY" value="" />
|
<option name="WORKING_DIRECTORY" value="" />
|
||||||
|
<option name="ENV_VARIABLES" />
|
||||||
<option name="PASS_PARENT_ENVS" value="true" />
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
<option name="TEST_SEARCH_SCOPE">
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
<value defaultName="singleModule" />
|
<value defaultName="singleModule" />
|
||||||
</option>
|
</option>
|
||||||
|
<envs />
|
||||||
<patterns />
|
<patterns />
|
||||||
<method />
|
<method />
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
17
.idea/runConfigurations/briar_headless.xml
generated
17
.idea/runConfigurations/briar_headless.xml
generated
@@ -1,17 +0,0 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
|
||||||
<configuration default="false" name="briar-headless" type="JetRunConfigurationType" factoryName="Kotlin" singleton="true">
|
|
||||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
|
||||||
<option name="VM_PARAMETERS" value="" />
|
|
||||||
<option name="PROGRAM_PARAMETERS" value="-v" />
|
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
|
||||||
<option name="PASS_PARENT_ENVS" value="true" />
|
|
||||||
<option name="MAIN_CLASS_NAME" value="org.briarproject.briar.headless.MainKt" />
|
|
||||||
<option name="WORKING_DIRECTORY" value="" />
|
|
||||||
<module name="briar-headless" />
|
|
||||||
<envs />
|
|
||||||
<method>
|
|
||||||
<option name="Gradle.BeforeRunTask" enabled="true" tasks="jar" externalProjectPath="$PROJECT_DIR$/briar-headless" vmOptions="" scriptParameters="" />
|
|
||||||
</method>
|
|
||||||
</configuration>
|
|
||||||
</component>
|
|
||||||
@@ -3,14 +3,14 @@ apply plugin: 'witness'
|
|||||||
apply from: 'witness.gradle'
|
apply from: 'witness.gradle'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 28
|
compileSdkVersion 27
|
||||||
buildToolsVersion '28.0.3'
|
buildToolsVersion '27.0.3'
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion 26
|
targetSdkVersion 26
|
||||||
versionCode 10103
|
versionCode 10101
|
||||||
versionName "1.1.3"
|
versionName "1.1.1"
|
||||||
consumerProguardFiles 'proguard-rules.txt'
|
consumerProguardFiles 'proguard-rules.txt'
|
||||||
|
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
@@ -28,7 +28,7 @@ configurations {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(path: ':bramble-core', configuration: 'default')
|
implementation project(path: ':bramble-core', configuration: 'default')
|
||||||
tor 'org.briarproject:tor-android:0.3.4.8@zip'
|
tor 'org.briarproject:tor-android:0.2.9.16@zip'
|
||||||
|
|
||||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
|
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
|
||||||
|
|
||||||
|
|||||||
@@ -1,153 +0,0 @@
|
|||||||
package org.briarproject.bramble.plugin.tor;
|
|
||||||
|
|
||||||
import org.spongycastle.crypto.tls.Certificate;
|
|
||||||
import org.spongycastle.crypto.tls.CipherSuite;
|
|
||||||
import org.spongycastle.crypto.tls.DefaultTlsClient;
|
|
||||||
import org.spongycastle.crypto.tls.ServerOnlyTlsAuthentication;
|
|
||||||
import org.spongycastle.crypto.tls.TlsAuthentication;
|
|
||||||
import org.spongycastle.crypto.tls.TlsClientProtocol;
|
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import static java.util.logging.Level.INFO;
|
|
||||||
|
|
||||||
public class TorProbe {
|
|
||||||
|
|
||||||
private static final Logger LOG =
|
|
||||||
Logger.getLogger(TorProbe.class.getName());
|
|
||||||
|
|
||||||
private static final int READ_TIMEOUT = 10 * 1000;
|
|
||||||
|
|
||||||
// https://trac.torproject.org/projects/tor/wiki/org/projects/Tor/TLSHistory
|
|
||||||
private static final int SSL3_RSA_FIPS_WITH_3DES_EDE_CBC_SHA = 0xfeff;
|
|
||||||
|
|
||||||
// https://gitweb.torproject.org/torspec.git/tree/tor-spec.txt#n347
|
|
||||||
private static final int[] TOR_CIPHER_SUITES = new int[] {
|
|
||||||
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
|
||||||
CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
|
||||||
CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
|
|
||||||
CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
|
|
||||||
CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
|
|
||||||
CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
|
|
||||||
CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA,
|
|
||||||
CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
|
||||||
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
|
||||||
CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
|
||||||
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
|
|
||||||
CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA,
|
|
||||||
CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
|
|
||||||
CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
|
|
||||||
CipherSuite.TLS_RSA_WITH_RC4_128_MD5,
|
|
||||||
CipherSuite.TLS_RSA_WITH_RC4_128_SHA,
|
|
||||||
CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
|
|
||||||
CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
SSL3_RSA_FIPS_WITH_3DES_EDE_CBC_SHA,
|
|
||||||
CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA
|
|
||||||
};
|
|
||||||
|
|
||||||
// https://gitweb.torproject.org/torspec.git/tree/tor-spec.txt#n412
|
|
||||||
private static final byte[] VERSIONS_CELL = new byte[] {
|
|
||||||
0x00, 0x00, // Circuit ID: 0
|
|
||||||
0x07, // Command: Versions
|
|
||||||
0x00, 0x06, // Payload length: 6 bytes
|
|
||||||
0x00, 0x03, 0x00, 0x04, 0x00, 0x05 // Supported versions: 3, 4, 5
|
|
||||||
};
|
|
||||||
|
|
||||||
public List<Integer> probe(String address, int port) throws IOException {
|
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Connecting to " + address + ":" + port);
|
|
||||||
Socket socket = new Socket(address, port);
|
|
||||||
LOG.info("Connected");
|
|
||||||
TlsClientProtocol client = new TlsClientProtocol(
|
|
||||||
socket.getInputStream(), socket.getOutputStream(),
|
|
||||||
new SecureRandom());
|
|
||||||
client.connect(new TorTlsClient());
|
|
||||||
LOG.info("TLS handshake succeeded");
|
|
||||||
socket.setSoTimeout(READ_TIMEOUT);
|
|
||||||
try {
|
|
||||||
// Send a versions cell
|
|
||||||
OutputStream out = client.getOutputStream();
|
|
||||||
out.write(VERSIONS_CELL);
|
|
||||||
out.flush();
|
|
||||||
LOG.info("Sent versions cell");
|
|
||||||
|
|
||||||
// Expect a versions cell in response
|
|
||||||
List<Integer> versions = new ArrayList<>();
|
|
||||||
DataInputStream in = new DataInputStream(client.getInputStream());
|
|
||||||
int circuitId = in.readUnsignedShort();
|
|
||||||
if (circuitId != 0)
|
|
||||||
throw new IOException("Unexpected circuit ID: " + circuitId);
|
|
||||||
int command = in.readUnsignedByte();
|
|
||||||
if (command != 7)
|
|
||||||
throw new IOException("Unexpected command: " + command);
|
|
||||||
int payloadLength = in.readUnsignedShort();
|
|
||||||
if (payloadLength == 0 || payloadLength % 2 != 0) {
|
|
||||||
throw new IOException("Invalid payload length: "
|
|
||||||
+ payloadLength);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < payloadLength / 2; i++) {
|
|
||||||
int version = in.readUnsignedShort();
|
|
||||||
versions.add(version);
|
|
||||||
}
|
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Supported versions: " + versions);
|
|
||||||
return versions;
|
|
||||||
} finally {
|
|
||||||
client.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
|
||||||
if (args.length != 2) {
|
|
||||||
System.err.println("Usage: TorProbe <address> <port>");
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
String address = args[0];
|
|
||||||
int port = Integer.parseInt(args[1]);
|
|
||||||
new TorProbe().probe(address, port);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class TorTlsClient extends DefaultTlsClient {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TlsAuthentication getAuthentication() {
|
|
||||||
return new ServerOnlyTlsAuthentication() {
|
|
||||||
@Override
|
|
||||||
public void notifyServerCertificate(Certificate cert)
|
|
||||||
throws IOException {
|
|
||||||
LOG.info("Received server certificate");
|
|
||||||
org.spongycastle.asn1.x509.Certificate[] chain =
|
|
||||||
cert.getCertificateList();
|
|
||||||
if (chain.length != 1)
|
|
||||||
throw new IOException("Certificate is not self-signed");
|
|
||||||
for (org.spongycastle.asn1.x509.Certificate c : chain) {
|
|
||||||
if (LOG.isLoggable(INFO)) {
|
|
||||||
LOG.info("Subject: " + c.getSubject());
|
|
||||||
LOG.info("Issuer: " + c.getIssuer());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[] getCipherSuites() {
|
|
||||||
return TOR_CIPHER_SUITES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +1,40 @@
|
|||||||
dependencyVerification {
|
dependencyVerification {
|
||||||
verify = [
|
verify = [
|
||||||
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
|
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
|
||||||
'com.android.tools.analytics-library:protos:26.2.1:protos-26.2.1.jar:2f371f5b1f551e85ab08be4d6a2873471b3d44afd1ebf6aa3298f3b796bf691f',
|
'com.android.tools.analytics-library:protos:26.1.3:protos-26.1.3.jar:818c9f256f141d9dafec03a1aa2b94d240b2c140acfd7ee31a8b3e6c2b9479e3',
|
||||||
'com.android.tools.analytics-library:shared:26.2.1:shared-26.2.1.jar:4c1e4e705fa4d45f23aaea230557f6508155012d9c296337787c1d7b26a97f5a',
|
'com.android.tools.analytics-library:shared:26.1.3:shared-26.1.3.jar:7110706c7ada96c8b6f5ca80c478291bc7899d46277de2c48527e045442401a3',
|
||||||
'com.android.tools.analytics-library:tracker:26.2.1:tracker-26.2.1.jar:4a624ecc976539f755ddb0bb8dfc2dd3d08326cfec59a098dbd70f701ca7fb75',
|
'com.android.tools.analytics-library:tracker:26.1.3:tracker-26.1.3.jar:4155424bf2ce4872da83332579a1707252bc66cbd77c5144fdc4483d0f2e1418',
|
||||||
'com.android.tools.build:aapt2:3.2.1-4818971:aapt2-3.2.1-4818971-linux.jar:f431b6f96c91a2c155144b091a9c97d9805c589fe8efc9c930b6cd346cb60a1e',
|
'com.android.tools.build:apksig:3.1.3:apksig-3.1.3.jar:7e1f8e675a6e768e5b56405e41d6c3cc05befe62e601b04177de1029902c9c89',
|
||||||
'com.android.tools.build:apksig:3.2.1:apksig-3.2.1.jar:2b46f2feffea66037aab29e4261b2433c190194a6ef97b958511eb157f2ccba5',
|
'com.android.tools.build:builder-model:3.1.3:builder-model-3.1.3.jar:06ad1c422d679fc698451479cb40ba863849d67bfd1de23f6d2c16d78b024b0b',
|
||||||
'com.android.tools.build:apkzlib:3.2.1:apkzlib-3.2.1.jar:c39ad0313905932431fe81c8899c2cf39a4d92ad6c4edcaa4b25432f461452aa',
|
'com.android.tools.build:builder-test-api:3.1.3:builder-test-api-3.1.3.jar:4d989f780436794f0f8b2f50e9e079b786571eac90f26c208ab2ae6d4012f389',
|
||||||
'com.android.tools.build:builder-model:3.2.1:builder-model-3.2.1.jar:a9f68e6abcec122f9cb5ad352d3f05a3eb03acbcdca95e4d25c16310c2c965ff',
|
'com.android.tools.build:builder:3.1.3:builder-3.1.3.jar:8a1092012c89d0ec1ee2eff09c5708c71ef4482a6862df8d3a44a67fccace01c',
|
||||||
'com.android.tools.build:builder-test-api:3.2.1:builder-test-api-3.2.1.jar:533ac6c2b5884bb54967a33791f2628dfdfac7981af39417a333b43d4379b6be',
|
'com.android.tools.build:gradle-api:3.1.3:gradle-api-3.1.3.jar:01e4df521456aef66514336f1d492346730dd1fb8f6433a89f62da834941ed72',
|
||||||
'com.android.tools.build:builder:3.2.1:builder-3.2.1.jar:aedcbfd115dbe91d09b4113e66ef50589b558d0aa3b2f133b1d867c9b87fae83',
|
'com.android.tools.build:manifest-merger:26.1.3:manifest-merger-26.1.3.jar:1e4fc7e932adb4607082409800e5e6fccb42e6c5360ae5990094bf522f3ada55',
|
||||||
'com.android.tools.build:gradle-api:3.2.1:gradle-api-3.2.1.jar:57cf0ac5ac1dca8afdb3f62b94265e776e7dcfa641cc3844fb53a05193de208d',
|
'com.android.tools.ddms:ddmlib:26.1.3:ddmlib-26.1.3.jar:c54931cd68df5d1ea2923b3b320eae47cd2307a5a916bb8674c0acf93cd1d3cd',
|
||||||
'com.android.tools.build:manifest-merger:26.2.1:manifest-merger-26.2.1.jar:8830573263361035d38cfdcb51e2db94029c93865b21334f5fbf8a27984281a6',
|
'com.android.tools.external.com-intellij:intellij-core:26.1.3:intellij-core-26.1.3.jar:af67f5535fef2e1a28b1007a4acb8c5deb6a1e33b8afe7b11d012c9e778ebcec',
|
||||||
'com.android.tools.ddms:ddmlib:26.2.1:ddmlib-26.2.1.jar:a4bf0a29a19980bf27269465cc782064656750b77c26728f82f9e148b705218b',
|
'com.android.tools.external.com-intellij:kotlin-compiler:26.1.3:kotlin-compiler-26.1.3.jar:c746d2859dc11cc05c84b692b3498d3a621e0929511f8440ee009c6557838fd4',
|
||||||
'com.android.tools.external.com-intellij:intellij-core:26.2.1:intellij-core-26.2.1.jar:4925ad1892c2687cb1a63427d440ef519c8c59215fefe0dc5d541d5d411fcafe',
|
'com.android.tools.external.org-jetbrains:uast:26.1.3:uast-26.1.3.jar:3f3f6651d0c7685a77ecb22e9c82d6b49fdf24322c17360768dc530678f43265',
|
||||||
'com.android.tools.external.com-intellij:kotlin-compiler:26.2.1:kotlin-compiler-26.2.1.jar:daa064fd708f340ee25fb9823c4c74104ac77f1370b76d907eb9ae6daec0a2ae',
|
'com.android.tools.layoutlib:layoutlib-api:26.1.3:layoutlib-api-26.1.3.jar:10bc73ce706c45629872d6a999dbe12116df64e24f47ff93b7b13121ff57b4b0',
|
||||||
'com.android.tools.external.org-jetbrains:uast:26.2.1:uast-26.2.1.jar:f10f7258d2ab9189562cc0f9ad838c0378fdba439229173390a99de02ebac75b',
|
'com.android.tools.lint:lint-api:26.1.3:lint-api-26.1.3.jar:6f97323f9af8deda86278717885b5c927f3766757db89709f52d11d42b6fb751',
|
||||||
'com.android.tools.layoutlib:layoutlib-api:26.2.1:layoutlib-api-26.2.1.jar:ddbf4fca123733fa011595b1cc1f4ac2937ed327b60990711fafc33c775c2ade',
|
'com.android.tools.lint:lint-checks:26.1.3:lint-checks-26.1.3.jar:73c3d53784c9ce3e6d5968506581918e0179645d20809927ca4a001dd766b001',
|
||||||
'com.android.tools.lint:lint-api:26.2.1:lint-api-26.2.1.jar:3b57e739de567b98bc9ab56c2c0ee66fc026b4adf5843e8f9804ca0666a6f66e',
|
'com.android.tools.lint:lint-gradle-api:26.1.3:lint-gradle-api-26.1.3.jar:7ca3c4866ec21dc21d53a9d86f752b77ace6f6c610a0c9dc877313856c733d9d',
|
||||||
'com.android.tools.lint:lint-checks:26.2.1:lint-checks-26.2.1.jar:c86f4cc9aaee722ee4ad70062f7b5af91e9b041914af27adc09f545ab0fb3bc6',
|
'com.android.tools.lint:lint-gradle:26.1.3:lint-gradle-26.1.3.jar:db0c354b8f4b6f6637e31f91c564785a59ff896325331fcbc3de7458e0b6c067',
|
||||||
'com.android.tools.lint:lint-gradle-api:26.2.1:lint-gradle-api-26.2.1.jar:2283e7af32e301565f2a797e531f0fc8c648077d457afb3ffdddbee638976c2f',
|
'com.android.tools.lint:lint-kotlin:26.1.3:lint-kotlin-26.1.3.jar:94e2b0f4565a241561cfb8fc1222bb3f132a3b98d2a90421dbb72ee8358e7d68',
|
||||||
'com.android.tools.lint:lint-gradle:26.2.1:lint-gradle-26.2.1.jar:8fd90b2f3ec788cbb9801c07ab3e1ea2255aa31a6093157d7ea0ff13d0315ecb',
|
'com.android.tools.lint:lint:26.1.3:lint-26.1.3.jar:8d5f32c989c6d191d712e90ad3ca2d1c409313599551d04d834caa44d26c78df',
|
||||||
'com.android.tools.lint:lint-kotlin:26.2.1:lint-kotlin-26.2.1.jar:7a6a5d2b18f69cf1b900d857c2632b4c683713c533295933b8b759f8cab4a877',
|
'com.android.tools:annotations:26.1.3:annotations-26.1.3.jar:c950430b24ac5d58fc97e7283b8f0115f99587e76e08b4e1e2aaa780f2d77323',
|
||||||
'com.android.tools.lint:lint:26.2.1:lint-26.2.1.jar:7848b82ae988b90dee259ae7c7e86e05cbf52db6cd21c8bbd38ce7df08f3f8c5',
|
'com.android.tools:common:26.1.3:common-26.1.3.jar:7c31a90581a148ab219f615a59667f0dded7fa39b248529784474da3c2274ef2',
|
||||||
'com.android.tools:annotations:26.2.1:annotations-26.2.1.jar:7391c6a1e080174b96e64ceb078dadd31ce4d8a2d2fee0ec65be202126f90f24',
|
'com.android.tools:dvlib:26.1.3:dvlib-26.1.3.jar:0cae87906f53d3f1088366a916ed180a7312b6d9919b90797f238875c8492855',
|
||||||
'com.android.tools:common:26.2.1:common-26.2.1.jar:a50aab2d6411ff68f4004a87c7e93d87d8e980a0ec3b352246549897ea2d78e5',
|
'com.android.tools:repository:26.1.3:repository-26.1.3.jar:52d4539cc68db91b261e2a33b2c8206b26e05539078758dc28cfb3854adb4f59',
|
||||||
'com.android.tools:dvlib:26.2.1:dvlib-26.2.1.jar:72a83bf2839b1df9b1fbf67ba45d1bfb9f966cd774da4320c762b2be8f1688aa',
|
'com.android.tools:sdk-common:26.1.3:sdk-common-26.1.3.jar:1948603ca9ff22c7ebb3178000bffa3a9dd2ca1cc5cb0c793cae08468b8fcfc1',
|
||||||
'com.android.tools:repository:26.2.1:repository-26.2.1.jar:fa74dae09103faef703df38550ad8fa244c5b6d1bf90d6198be932292b3d9cc1',
|
'com.android.tools:sdklib:26.1.3:sdklib-26.1.3.jar:4adcfaad9514607098d2c51503c39811112d3050f4d1e744c01c7f08f591032b',
|
||||||
'com.android.tools:sdk-common:26.2.1:sdk-common-26.2.1.jar:759d4b292ca69a35cf961fca377b54158fc6c88108978006999442e80a011cf4',
|
|
||||||
'com.android.tools:sdklib:26.2.1:sdklib-26.2.1.jar:248df7ad5eac4aeb6f96c394c76760de4b7b89ac056e54d0c21a739368b91b45',
|
|
||||||
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed',
|
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed',
|
||||||
'com.google.code.gson:gson:2.8.0:gson-2.8.0.jar:c6221763bd79c4f1c3dc7f750b5f29a0bb38b367b81314c4f71896e340c40825',
|
'com.google.code.gson:gson:2.7:gson-2.7.jar:2d43eb5ea9e133d2ee2405cc14f5ee08951b8361302fdd93494a3a997b508d32',
|
||||||
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
|
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
|
||||||
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
|
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
|
||||||
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
||||||
'com.google.errorprone:error_prone_annotations:2.0.18:error_prone_annotations-2.0.18.jar:cb4cfad870bf563a07199f3ebea5763f0dec440fcda0b318640b1feaa788656b',
|
'com.google.errorprone:error_prone_annotations:2.0.18:error_prone_annotations-2.0.18.jar:cb4cfad870bf563a07199f3ebea5763f0dec440fcda0b318640b1feaa788656b',
|
||||||
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
||||||
'com.google.guava:guava:23.0:guava-23.0.jar:7baa80df284117e5b945b19b98d367a85ea7b7801bd358ff657946c3bd1b6596',
|
'com.google.guava:guava:22.0:guava-22.0.jar:1158e94c7de4da480873f0b4ab4a1da14c0d23d4b1902cc94a58a6f0f9ab579e',
|
||||||
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:40ceb7157feb263949e0f503fe5f71689333a621021aa20ce0d0acee3badaa0f',
|
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:40ceb7157feb263949e0f503fe5f71689333a621021aa20ce0d0acee3badaa0f',
|
||||||
'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd',
|
'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd',
|
||||||
'com.google.protobuf:protobuf-java:3.4.0:protobuf-java-3.4.0.jar:dce7e66b32456a1b1198da0caff3a8acb71548658391e798c79369241e6490a4',
|
'com.google.protobuf:protobuf-java:3.4.0:protobuf-java-3.4.0.jar:dce7e66b32456a1b1198da0caff3a8acb71548658391e798c79369241e6490a4',
|
||||||
@@ -45,8 +43,8 @@ dependencyVerification {
|
|||||||
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
|
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
|
||||||
'com.sun.istack:istack-commons-runtime:2.21:istack-commons-runtime-2.21.jar:c33e67a0807095f02a0e2da139412dd7c4f9cc1a4c054b3e434f96831ba950f4',
|
'com.sun.istack:istack-commons-runtime:2.21:istack-commons-runtime-2.21.jar:c33e67a0807095f02a0e2da139412dd7c4f9cc1a4c054b3e434f96831ba950f4',
|
||||||
'com.sun.xml.fastinfoset:FastInfoset:1.2.13:FastInfoset-1.2.13.jar:27a77db909f3c2833c0b1a37c55af1db06045118ad2eed96ce567b6632bce038',
|
'com.sun.xml.fastinfoset:FastInfoset:1.2.13:FastInfoset-1.2.13.jar:27a77db909f3c2833c0b1a37c55af1db06045118ad2eed96ce567b6632bce038',
|
||||||
'commons-codec:commons-codec:1.9:commons-codec-1.9.jar:ad19d2601c3abf0b946b5c3a4113e226a8c1e3305e395b90013b78dd94a723ce',
|
'commons-codec:commons-codec:1.6:commons-codec-1.6.jar:54b34e941b8e1414bd3e40d736efd3481772dc26db3296f6aa45cec9f6203d86',
|
||||||
'commons-logging:commons-logging:1.2:commons-logging-1.2.jar:daddea1ea0be0f56978ab3006b8ac92834afeefbd9b7e4e6316fca57df0fa636',
|
'commons-logging:commons-logging:1.1.1:commons-logging-1.1.1.jar:ce6f913cad1f0db3aad70186d65c5bc7ffcc9a99e3fe8e0b137312819f7c362f',
|
||||||
'it.unimi.dsi:fastutil:7.2.0:fastutil-7.2.0.jar:74fa208043740642f7e6eb09faba15965218ad2f50ce3020efb100136e4b591c',
|
'it.unimi.dsi:fastutil:7.2.0:fastutil-7.2.0.jar:74fa208043740642f7e6eb09faba15965218ad2f50ce3020efb100136e4b591c',
|
||||||
'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',
|
||||||
@@ -57,13 +55,13 @@ dependencyVerification {
|
|||||||
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
||||||
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
|
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
|
||||||
'org.apache.commons:commons-compress:1.12:commons-compress-1.12.jar:2c1542faf343185b7cab9c3d55c8ae5471d6d095d3887a4adefdbdf2984dc0b6',
|
'org.apache.commons:commons-compress:1.12:commons-compress-1.12.jar:2c1542faf343185b7cab9c3d55c8ae5471d6d095d3887a4adefdbdf2984dc0b6',
|
||||||
'org.apache.httpcomponents:httpclient:4.5.2:httpclient-4.5.2.jar:0dffc621400d6c632f55787d996b8aeca36b30746a716e079a985f24d8074057',
|
'org.apache.httpcomponents:httpclient:4.2.6:httpclient-4.2.6.jar:362e9324ee7c697e21279e20077b52737ddef3f1b2c1a7abe5ad34b465145550',
|
||||||
'org.apache.httpcomponents:httpcore:4.4.5:httpcore-4.4.5.jar:64d5453874cab7e40a7065cb01a9a9ca1053845a9786b478878b679e0580cec3',
|
'org.apache.httpcomponents:httpcore:4.2.5:httpcore-4.2.5.jar:e5e82da4cc66c8d917bbf743e3c0752efe8522735e7fc9dbddb65bccea81cfe9',
|
||||||
'org.apache.httpcomponents:httpmime:4.5.2:httpmime-4.5.2.jar:231a3f7e4962053db2be8461d5422e68fc458a3a7dd7d8ada803a348e21f8f07',
|
'org.apache.httpcomponents:httpmime:4.1:httpmime-4.1.jar:31629566148e8a47688ae43b420abc3ecd783ed15b33bebc00824bf24c9b15aa',
|
||||||
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
|
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
|
||||||
'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
|
'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
|
||||||
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
|
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
|
||||||
'org.briarproject:tor-android:0.3.4.8:tor-android-0.3.4.8.zip:989a0352d9d8d8172cd6c2137654e165e5d2beb10ed1211bab3814e224ad1926',
|
'org.briarproject:tor-android:0.2.9.16:tor-android-0.2.9.16.zip:515e33dda6a30853c885a2de2c79ae1ab9ad8b6db44f5db8890333ec2e24f4ae',
|
||||||
'org.codehaus.groovy:groovy-all:2.4.12:groovy-all-2.4.12.jar:6a56af4bd48903d56bec62821876cadefafd007360cc6bd0d8f7aa8d72b38be4',
|
'org.codehaus.groovy:groovy-all:2.4.12:groovy-all-2.4.12.jar:6a56af4bd48903d56bec62821876cadefafd007360cc6bd0d8f7aa8d72b38be4',
|
||||||
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
|
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
|
||||||
'org.glassfish.jaxb:jaxb-core:2.2.11:jaxb-core-2.2.11.jar:37bcaee8ebb04362c8352a5bf6221b86967ecdab5164c696b10b9a2bb587b2aa',
|
'org.glassfish.jaxb:jaxb-core:2.2.11:jaxb-core-2.2.11.jar:37bcaee8ebb04362c8352a5bf6221b86967ecdab5164c696b10b9a2bb587b2aa',
|
||||||
@@ -72,10 +70,9 @@ dependencyVerification {
|
|||||||
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
|
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
|
||||||
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
|
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
|
||||||
'org.jetbrains.kotlin:kotlin-reflect:1.2.0:kotlin-reflect-1.2.0.jar:4f48a872bad6e4d9c053f4ad610d11e4012ad7e58dc19a03dd5eb811f36069dd',
|
'org.jetbrains.kotlin:kotlin-reflect:1.2.0:kotlin-reflect-1.2.0.jar:4f48a872bad6e4d9c053f4ad610d11e4012ad7e58dc19a03dd5eb811f36069dd',
|
||||||
'org.jetbrains.kotlin:kotlin-stdlib-common:1.2.71:kotlin-stdlib-common-1.2.71.jar:63999687ff2fce8a592dd180ffbbf8f1d21c26b4044c55cdc74ff3cf3b3cf328',
|
'org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.0:kotlin-stdlib-jre7-1.2.0.jar:c7a20fb951d437797afe8980aff6c1e5a03f310c661ba58ba1d4fa90cb0f2926',
|
||||||
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.71:kotlin-stdlib-jdk7-1.2.71.jar:b136bd61b240e07d4d92ce00d3bd1dbf584400a7bf5f220c2f3cd22446858082',
|
'org.jetbrains.kotlin:kotlin-stdlib-jre8:1.2.0:kotlin-stdlib-jre8-1.2.0.jar:633524eee6ef1941f7cb1dab7ee3927b0a221ceee9047aeb5515f4cbb990c82a',
|
||||||
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.71:kotlin-stdlib-jdk8-1.2.71.jar:ac3c8abf47790b64b4f7e2509a53f0c145e061ac1612a597520535d199946ea9',
|
'org.jetbrains.kotlin:kotlin-stdlib:1.2.0:kotlin-stdlib-1.2.0.jar:05cfd9f5ac0b41910703a8925f7211a495909b27a2ffdd1c5106f1689aeafcd4',
|
||||||
'org.jetbrains.kotlin:kotlin-stdlib:1.2.71:kotlin-stdlib-1.2.71.jar:4c895c270b87f5fec2a2796e1d89c15407ee821de961527c28588bb46afbc68b',
|
|
||||||
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
|
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
|
||||||
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
|
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
|
||||||
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
|
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
|
||||||
@@ -84,11 +81,11 @@ dependencyVerification {
|
|||||||
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
|
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
|
||||||
'org.jvnet.staxex:stax-ex:1.7.7:stax-ex-1.7.7.jar:a31ff7d77163c0deb09e7fee59ad35ae44c2cee2cc8552a116ccd1583d813fb4',
|
'org.jvnet.staxex:stax-ex:1.7.7:stax-ex-1.7.7.jar:a31ff7d77163c0deb09e7fee59ad35ae44c2cee2cc8552a116ccd1583d813fb4',
|
||||||
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
|
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
|
||||||
'org.ow2.asm:asm-analysis:6.0:asm-analysis-6.0.jar:2f1a6387219c3a6cc4856481f221b03bd9f2408a326d416af09af5d6f608c1f4',
|
'org.ow2.asm:asm-analysis:5.1:asm-analysis-5.1.jar:a34658f5c5de4b573eef21131cc32cc25f7b66407944f312b28ec2e56abb1fa9',
|
||||||
'org.ow2.asm:asm-commons:6.0:asm-commons-6.0.jar:f1bce5c648a96a017bdcd01fe5d59af9845297fd7b79b81c015a6fbbd9719abf',
|
'org.ow2.asm:asm-commons:5.1:asm-commons-5.1.jar:97b3786e1f55e74bddf8ad102bf50e33bbcbc1f6b7fd7b36f0bbbb25cd4981be',
|
||||||
'org.ow2.asm:asm-tree:6.0:asm-tree-6.0.jar:887998fb69727c8759e4d253f856822801e33f9fd4caa566b3ac58ee92106215',
|
'org.ow2.asm:asm-tree:5.1:asm-tree-5.1.jar:c0de2bbc4cb8297419659813ecd4ed1d077ed1dd5c1f5544cc5143e493e84c10',
|
||||||
'org.ow2.asm:asm-util:6.0:asm-util-6.0.jar:356afebdb0f870175262e5188f8709a3b17aa2a5a6a4b0340b04d4b449bca5f6',
|
'org.ow2.asm:asm-util:5.1:asm-util-5.1.jar:ee032c39ae5e3cd099148fbba9a2124f9ed613e5cb93e03ee0fa8808ce364040',
|
||||||
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
|
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
|
||||||
'org.ow2.asm:asm:6.0:asm-6.0.jar:dd8971c74a4e697899a8e95caae4ea8760ea6c486dc6b97b1795e75760420461',
|
'org.ow2.asm:asm:5.1:asm-5.1.jar:d2da399a9967c69f0a21739256fa79d284222c223082cacadc17372244764b54',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
package org.briarproject.bramble.api;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|
||||||
|
|
||||||
@NotNullByDefault
|
|
||||||
public interface Nameable {
|
|
||||||
|
|
||||||
String getName();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -38,18 +38,4 @@ public abstract class StringMap extends Hashtable<String, String> {
|
|||||||
public void putInt(String key, int value) {
|
public void putInt(String key, int value) {
|
||||||
put(key, String.valueOf(value));
|
put(key, String.valueOf(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLong(String key, long defaultValue) {
|
|
||||||
String s = get(key);
|
|
||||||
if (s == null) return defaultValue;
|
|
||||||
try {
|
|
||||||
return Long.valueOf(s);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void putLong(String key, long value) {
|
|
||||||
put(key, String.valueOf(value));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package org.briarproject.bramble.api;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An exception that indicates an unrecoverable version mismatch.
|
||||||
|
*/
|
||||||
|
public class UnsupportedVersionException extends IOException {
|
||||||
|
}
|
||||||
@@ -48,8 +48,12 @@ public abstract class BdfMessageValidator implements MessageValidator {
|
|||||||
throw new InvalidMessageException(
|
throw new InvalidMessageException(
|
||||||
"Timestamp is too far in the future");
|
"Timestamp is too far in the future");
|
||||||
}
|
}
|
||||||
|
byte[] body = m.getBody();
|
||||||
|
if (body.length == 0) {
|
||||||
|
throw new InvalidMessageException("Message is too short");
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
BdfList bodyList = clientHelper.toList(m.getBody());
|
BdfList bodyList = clientHelper.toList(body);
|
||||||
BdfMessageContext result = validateMessage(m, g, bodyList);
|
BdfMessageContext result = validateMessage(m, g, bodyList);
|
||||||
Metadata meta = metadataEncoder.encode(result.getDictionary());
|
Metadata meta = metadataEncoder.encode(result.getDictionary());
|
||||||
return new MessageContext(meta, result.getDependencies());
|
return new MessageContext(meta, result.getDependencies());
|
||||||
|
|||||||
@@ -76,19 +76,6 @@ public interface DatabaseComponent {
|
|||||||
*/
|
*/
|
||||||
void endTransaction(Transaction txn);
|
void endTransaction(Transaction txn);
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs the given task within a transaction.
|
|
||||||
*/
|
|
||||||
<E extends Exception> void transaction(boolean readOnly,
|
|
||||||
DbRunnable<E> task) throws DbException, E;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs the given task within a transaction and returns the result of the
|
|
||||||
* task.
|
|
||||||
*/
|
|
||||||
<R, E extends Exception> R transactionWithResult(boolean readOnly,
|
|
||||||
DbCallable<R, E> task) throws DbException, E;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores a contact associated with the given local and remote pseudonyms,
|
* Stores a contact associated with the given local and remote pseudonyms,
|
||||||
* and returns an ID for the contact.
|
* and returns an ID for the contact.
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
package org.briarproject.bramble.api.db;
|
|
||||||
|
|
||||||
public interface DbCallable<R, E extends Exception> {
|
|
||||||
|
|
||||||
R call(Transaction txn) throws DbException, E;
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
package org.briarproject.bramble.api.db;
|
|
||||||
|
|
||||||
public interface DbRunnable<E extends Exception> {
|
|
||||||
|
|
||||||
void run(Transaction txn) throws DbException, E;
|
|
||||||
}
|
|
||||||
@@ -6,10 +6,6 @@ public interface MigrationListener {
|
|||||||
* This is called when a migration is started while opening the database.
|
* This is called when a migration is started while opening the database.
|
||||||
* It will be called once for each migration being applied.
|
* It will be called once for each migration being applied.
|
||||||
*/
|
*/
|
||||||
void onDatabaseMigration();
|
void onMigrationRun();
|
||||||
|
|
||||||
/**
|
|
||||||
* This is called when compaction is started while opening the database.
|
|
||||||
*/
|
|
||||||
void onDatabaseCompaction();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.briarproject.bramble.api.identity;
|
package org.briarproject.bramble.api.identity;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.Nameable;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.util.StringUtils;
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
|
|
||||||
@@ -14,7 +13,7 @@ import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_K
|
|||||||
*/
|
*/
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class Author implements Nameable {
|
public class Author {
|
||||||
|
|
||||||
public enum Status {
|
public enum Status {
|
||||||
NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES
|
NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES
|
||||||
|
|||||||
@@ -3,13 +3,7 @@ package org.briarproject.bramble.api.keyagreement;
|
|||||||
public interface KeyAgreementConstants {
|
public interface KeyAgreementConstants {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The version of the BQP protocol used in beta releases. This version
|
* The current version of the BQP protocol. Version number 89 is reserved.
|
||||||
* number is reserved.
|
|
||||||
*/
|
|
||||||
byte BETA_PROTOCOL_VERSION = 89;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The current version of the BQP protocol.
|
|
||||||
*/
|
*/
|
||||||
byte PROTOCOL_VERSION = 4;
|
byte PROTOCOL_VERSION = 4;
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
package org.briarproject.bramble.api.keyagreement;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Thrown when a QR code that has been scanned uses a protocol version that is
|
|
||||||
* not supported.
|
|
||||||
*/
|
|
||||||
public class UnsupportedVersionException extends IOException {
|
|
||||||
|
|
||||||
private final boolean tooOld;
|
|
||||||
|
|
||||||
public UnsupportedVersionException(boolean tooOld) {
|
|
||||||
this.tooOld = tooOld;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isTooOld() {
|
|
||||||
return tooOld;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -34,8 +34,7 @@ public interface LifecycleManager {
|
|||||||
*/
|
*/
|
||||||
enum LifecycleState {
|
enum LifecycleState {
|
||||||
|
|
||||||
STARTING, MIGRATING_DATABASE, COMPACTING_DATABASE, STARTING_SERVICES,
|
STARTING, MIGRATING_DATABASE, STARTING_SERVICES, RUNNING, STOPPING;
|
||||||
RUNNING, STOPPING;
|
|
||||||
|
|
||||||
public boolean isAfter(LifecycleState state) {
|
public boolean isAfter(LifecycleState state) {
|
||||||
return ordinal() > state.ordinal();
|
return ordinal() > state.ordinal();
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ public interface TorConstants {
|
|||||||
|
|
||||||
TransportId ID = new TransportId("org.briarproject.bramble.tor");
|
TransportId ID = new TransportId("org.briarproject.bramble.tor");
|
||||||
|
|
||||||
String PROP_ONION_V2 = "onion";
|
String PROP_ONION = "onion";
|
||||||
String PROP_ONION_V3 = "onion3";
|
|
||||||
|
|
||||||
int SOCKS_PORT = 59050;
|
int SOCKS_PORT = 59050;
|
||||||
int CONTROL_PORT = 59051;
|
int CONTROL_PORT = 59051;
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ public class Message {
|
|||||||
private final byte[] body;
|
private final byte[] body;
|
||||||
|
|
||||||
public Message(MessageId id, GroupId groupId, long timestamp, byte[] body) {
|
public Message(MessageId id, GroupId groupId, long timestamp, byte[] body) {
|
||||||
if (body.length == 0) throw new IllegalArgumentException();
|
|
||||||
if (body.length > MAX_MESSAGE_BODY_LENGTH)
|
if (body.length > MAX_MESSAGE_BODY_LENGTH)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
package org.briarproject.bramble.test;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.system.Clock;
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
|
|
||||||
public class SettableClock implements Clock {
|
|
||||||
|
|
||||||
private final AtomicLong time;
|
|
||||||
|
|
||||||
public SettableClock(AtomicLong time) {
|
|
||||||
this.time = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long currentTimeMillis() {
|
|
||||||
return time.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sleep(long milliseconds) throws InterruptedException {
|
|
||||||
Thread.sleep(milliseconds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,7 @@ dependencies {
|
|||||||
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 '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.4.1'
|
||||||
implementation 'org.briarproject:jtorctl:0.3'
|
implementation 'org.briarproject:jtorctl:0.3'
|
||||||
|
|
||||||
apt 'com.google.dagger:dagger-compiler:2.0.2'
|
apt 'com.google.dagger:dagger-compiler:2.0.2'
|
||||||
|
|||||||
@@ -9,9 +9,7 @@ import org.briarproject.bramble.api.contact.event.ContactVerifiedEvent;
|
|||||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.api.db.ContactExistsException;
|
import org.briarproject.bramble.api.db.ContactExistsException;
|
||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
import org.briarproject.bramble.api.db.DbCallable;
|
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.db.DbRunnable;
|
|
||||||
import org.briarproject.bramble.api.db.Metadata;
|
import org.briarproject.bramble.api.db.Metadata;
|
||||||
import org.briarproject.bramble.api.db.MigrationListener;
|
import org.briarproject.bramble.api.db.MigrationListener;
|
||||||
import org.briarproject.bramble.api.db.NoSuchContactException;
|
import org.briarproject.bramble.api.db.NoSuchContactException;
|
||||||
@@ -168,31 +166,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
for (Event e : transaction.getEvents()) eventBus.broadcast(e);
|
for (Event e : transaction.getEvents()) eventBus.broadcast(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public <E extends Exception> void transaction(boolean readOnly,
|
|
||||||
DbRunnable<E> task) throws DbException, E {
|
|
||||||
Transaction txn = startTransaction(readOnly);
|
|
||||||
try {
|
|
||||||
task.run(txn);
|
|
||||||
commitTransaction(txn);
|
|
||||||
} finally {
|
|
||||||
endTransaction(txn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <R, E extends Exception> R transactionWithResult(boolean readOnly,
|
|
||||||
DbCallable<R, E> task) throws DbException, E {
|
|
||||||
Transaction txn = startTransaction(readOnly);
|
|
||||||
try {
|
|
||||||
R result = task.call(txn);
|
|
||||||
commitTransaction(txn);
|
|
||||||
return result;
|
|
||||||
} finally {
|
|
||||||
endTransaction(txn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private T unbox(Transaction transaction) {
|
private T unbox(Transaction transaction) {
|
||||||
if (transaction.isCommitted()) throw new IllegalStateException();
|
if (transaction.isCommitted()) throw new IllegalStateException();
|
||||||
return txnClass.cast(transaction.unbox());
|
return txnClass.cast(transaction.unbox());
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ package org.briarproject.bramble.db;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.settings.Settings;
|
import org.briarproject.bramble.api.settings.Settings;
|
||||||
|
|
||||||
import static java.util.concurrent.TimeUnit.DAYS;
|
|
||||||
|
|
||||||
interface DatabaseConstants {
|
interface DatabaseConstants {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,16 +23,4 @@ interface DatabaseConstants {
|
|||||||
*/
|
*/
|
||||||
String SCHEMA_VERSION_KEY = "schemaVersion";
|
String SCHEMA_VERSION_KEY = "schemaVersion";
|
||||||
|
|
||||||
/**
|
|
||||||
* The {@link Settings} key under which the time of the last database
|
|
||||||
* compaction is stored.
|
|
||||||
*/
|
|
||||||
String LAST_COMPACTED_KEY = "lastCompacted";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The maximum time between database compactions in milliseconds. When the
|
|
||||||
* database is opened it will be compacted if more than this amount of time
|
|
||||||
* has passed since the last compaction.
|
|
||||||
*/
|
|
||||||
long MAX_COMPACTION_INTERVAL_MS = DAYS.toMillis(30);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import java.io.File;
|
|||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.DriverManager;
|
import java.sql.DriverManager;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Statement;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -107,22 +106,4 @@ class H2Database extends JdbcDatabase {
|
|||||||
String getUrl() {
|
String getUrl() {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void compactAndClose() throws DbException {
|
|
||||||
Connection c = null;
|
|
||||||
Statement s = null;
|
|
||||||
try {
|
|
||||||
c = createConnection();
|
|
||||||
closeAllConnections();
|
|
||||||
s = c.createStatement();
|
|
||||||
s.execute("SHUTDOWN COMPACT");
|
|
||||||
s.close();
|
|
||||||
c.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
tryToClose(s);
|
|
||||||
tryToClose(c);
|
|
||||||
throw new DbException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,18 +61,14 @@ class HyperSqlDatabase extends JdbcDatabase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws DbException {
|
public void close() throws DbException {
|
||||||
Connection c = null;
|
|
||||||
Statement s = null;
|
|
||||||
try {
|
try {
|
||||||
super.closeAllConnections();
|
super.closeAllConnections();
|
||||||
c = createConnection();
|
Connection c = createConnection();
|
||||||
s = c.createStatement();
|
Statement s = c.createStatement();
|
||||||
s.executeQuery("SHUTDOWN");
|
s.executeQuery("SHUTDOWN");
|
||||||
s.close();
|
s.close();
|
||||||
c.close();
|
c.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
tryToClose(s);
|
|
||||||
tryToClose(c);
|
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,22 +104,4 @@ class HyperSqlDatabase extends JdbcDatabase {
|
|||||||
String hex = StringUtils.toHexString(key.getBytes());
|
String hex = StringUtils.toHexString(key.getBytes());
|
||||||
return DriverManager.getConnection(url + ";crypt_key=" + hex);
|
return DriverManager.getConnection(url + ";crypt_key=" + hex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void compactAndClose() throws DbException {
|
|
||||||
Connection c = null;
|
|
||||||
Statement s = null;
|
|
||||||
try {
|
|
||||||
super.closeAllConnections();
|
|
||||||
c = createConnection();
|
|
||||||
s = c.createStatement();
|
|
||||||
s.executeQuery("SHUTDOWN COMPACT");
|
|
||||||
s.close();
|
|
||||||
c.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
tryToClose(s);
|
|
||||||
tryToClose(c);
|
|
||||||
throw new DbException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,13 +67,9 @@ import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERE
|
|||||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
|
||||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
|
||||||
import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
|
import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
|
||||||
import static org.briarproject.bramble.db.DatabaseConstants.LAST_COMPACTED_KEY;
|
|
||||||
import static org.briarproject.bramble.db.DatabaseConstants.MAX_COMPACTION_INTERVAL_MS;
|
|
||||||
import static org.briarproject.bramble.db.DatabaseConstants.SCHEMA_VERSION_KEY;
|
import static org.briarproject.bramble.db.DatabaseConstants.SCHEMA_VERSION_KEY;
|
||||||
import static org.briarproject.bramble.db.ExponentialBackoff.calculateExpiry;
|
import static org.briarproject.bramble.db.ExponentialBackoff.calculateExpiry;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.bramble.util.LogUtils.now;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A generic database implementation that can be used with any JDBC-compatible
|
* A generic database implementation that can be used with any JDBC-compatible
|
||||||
@@ -321,10 +317,9 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
private int openConnections = 0; // Locking: connectionsLock
|
private int openConnections = 0; // Locking: connectionsLock
|
||||||
private boolean closed = false; // Locking: connectionsLock
|
private boolean closed = false; // Locking: connectionsLock
|
||||||
|
|
||||||
|
@Nullable
|
||||||
protected abstract Connection createConnection() throws SQLException;
|
protected abstract Connection createConnection() throws SQLException;
|
||||||
|
|
||||||
protected abstract void compactAndClose() throws DbException;
|
|
||||||
|
|
||||||
private final Lock connectionsLock = new ReentrantLock();
|
private final Lock connectionsLock = new ReentrantLock();
|
||||||
private final Condition connectionsChanged = connectionsLock.newCondition();
|
private final Condition connectionsChanged = connectionsLock.newCondition();
|
||||||
|
|
||||||
@@ -349,16 +344,13 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
// Open the database and create the tables and indexes if necessary
|
// Open the database and create the tables and indexes if necessary
|
||||||
boolean compact;
|
|
||||||
Connection txn = startTransaction();
|
Connection txn = startTransaction();
|
||||||
try {
|
try {
|
||||||
if (reopen) {
|
if (reopen) {
|
||||||
Settings s = getSettings(txn, DB_SETTINGS_NAMESPACE);
|
checkSchemaVersion(txn, listener);
|
||||||
compact = migrateSchema(txn, s, listener) || isCompactionDue(s);
|
|
||||||
} else {
|
} else {
|
||||||
createTables(txn);
|
createTables(txn);
|
||||||
initialiseSettings(txn);
|
storeSchemaVersion(txn, CODE_SCHEMA_VERSION);
|
||||||
compact = false;
|
|
||||||
}
|
}
|
||||||
createIndexes(txn);
|
createIndexes(txn);
|
||||||
commitTransaction(txn);
|
commitTransaction(txn);
|
||||||
@@ -366,25 +358,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
abortTransaction(txn);
|
abortTransaction(txn);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
// Compact the database if necessary
|
|
||||||
if (compact) {
|
|
||||||
if (listener != null) listener.onDatabaseCompaction();
|
|
||||||
long start = now();
|
|
||||||
compactAndClose();
|
|
||||||
logDuration(LOG, "Compacting database", start);
|
|
||||||
// Allow the next transaction to reopen the DB
|
|
||||||
synchronized (connectionsLock) {
|
|
||||||
closed = false;
|
|
||||||
}
|
|
||||||
txn = startTransaction();
|
|
||||||
try {
|
|
||||||
storeLastCompacted(txn);
|
|
||||||
commitTransaction(txn);
|
|
||||||
} catch (DbException e) {
|
|
||||||
abortTransaction(txn);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -392,18 +365,17 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
* version used by the current code and applies any suitable migrations to
|
* version used by the current code and applies any suitable migrations to
|
||||||
* the data if necessary.
|
* the data if necessary.
|
||||||
*
|
*
|
||||||
* @return true if any migrations were applied, false if the schema was
|
|
||||||
* already current
|
|
||||||
* @throws DataTooNewException if the data uses a newer schema than the
|
* @throws DataTooNewException if the data uses a newer schema than the
|
||||||
* current code
|
* current code
|
||||||
* @throws DataTooOldException if the data uses an older schema than the
|
* @throws DataTooOldException if the data uses an older schema than the
|
||||||
* current code and cannot be migrated
|
* current code and cannot be migrated
|
||||||
*/
|
*/
|
||||||
private boolean migrateSchema(Connection txn, Settings s,
|
private void checkSchemaVersion(Connection txn,
|
||||||
@Nullable MigrationListener listener) throws DbException {
|
@Nullable MigrationListener listener) throws DbException {
|
||||||
|
Settings s = getSettings(txn, DB_SETTINGS_NAMESPACE);
|
||||||
int dataSchemaVersion = s.getInt(SCHEMA_VERSION_KEY, -1);
|
int dataSchemaVersion = s.getInt(SCHEMA_VERSION_KEY, -1);
|
||||||
if (dataSchemaVersion == -1) throw new DbException();
|
if (dataSchemaVersion == -1) throw new DbException();
|
||||||
if (dataSchemaVersion == CODE_SCHEMA_VERSION) return false;
|
if (dataSchemaVersion == CODE_SCHEMA_VERSION) return;
|
||||||
if (CODE_SCHEMA_VERSION < dataSchemaVersion)
|
if (CODE_SCHEMA_VERSION < dataSchemaVersion)
|
||||||
throw new DataTooNewException();
|
throw new DataTooNewException();
|
||||||
// Apply any suitable migrations in order
|
// Apply any suitable migrations in order
|
||||||
@@ -412,7 +384,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
if (start == dataSchemaVersion) {
|
if (start == dataSchemaVersion) {
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Migrating from schema " + start + " to " + end);
|
LOG.info("Migrating from schema " + start + " to " + end);
|
||||||
if (listener != null) listener.onDatabaseMigration();
|
if (listener != null) listener.onMigrationRun();
|
||||||
// Apply the migration
|
// Apply the migration
|
||||||
m.migrate(txn);
|
m.migrate(txn);
|
||||||
// Store the new schema version
|
// Store the new schema version
|
||||||
@@ -422,7 +394,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
if (dataSchemaVersion != CODE_SCHEMA_VERSION)
|
if (dataSchemaVersion != CODE_SCHEMA_VERSION)
|
||||||
throw new DataTooOldException();
|
throw new DataTooOldException();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Package access for testing
|
// Package access for testing
|
||||||
@@ -430,14 +401,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
return Arrays.asList(new Migration38_39(), new Migration39_40());
|
return Arrays.asList(new Migration38_39(), new Migration39_40());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isCompactionDue(Settings s) {
|
|
||||||
long lastCompacted = s.getLong(LAST_COMPACTED_KEY, 0);
|
|
||||||
long elapsed = clock.currentTimeMillis() - lastCompacted;
|
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info(elapsed + " ms since last compaction");
|
|
||||||
return elapsed > MAX_COMPACTION_INTERVAL_MS;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void storeSchemaVersion(Connection txn, int version)
|
private void storeSchemaVersion(Connection txn, int version)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
Settings s = new Settings();
|
Settings s = new Settings();
|
||||||
@@ -445,19 +408,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
mergeSettings(txn, s, DB_SETTINGS_NAMESPACE);
|
mergeSettings(txn, s, DB_SETTINGS_NAMESPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void storeLastCompacted(Connection txn) throws DbException {
|
|
||||||
Settings s = new Settings();
|
|
||||||
s.putLong(LAST_COMPACTED_KEY, clock.currentTimeMillis());
|
|
||||||
mergeSettings(txn, s, DB_SETTINGS_NAMESPACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initialiseSettings(Connection txn) throws DbException {
|
|
||||||
Settings s = new Settings();
|
|
||||||
s.putInt(SCHEMA_VERSION_KEY, CODE_SCHEMA_VERSION);
|
|
||||||
s.putLong(LAST_COMPACTED_KEY, clock.currentTimeMillis());
|
|
||||||
mergeSettings(txn, s, DB_SETTINGS_NAMESPACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void tryToClose(@Nullable ResultSet rs) {
|
private void tryToClose(@Nullable ResultSet rs) {
|
||||||
try {
|
try {
|
||||||
if (rs != null) rs.close();
|
if (rs != null) rs.close();
|
||||||
@@ -466,7 +416,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void tryToClose(@Nullable Statement s) {
|
private void tryToClose(@Nullable Statement s) {
|
||||||
try {
|
try {
|
||||||
if (s != null) s.close();
|
if (s != null) s.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
@@ -474,14 +424,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void tryToClose(@Nullable Connection c) {
|
|
||||||
try {
|
|
||||||
if (c != null) c.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
logException(LOG, WARNING, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createTables(Connection txn) throws DbException {
|
private void createTables(Connection txn) throws DbException {
|
||||||
Statement s = null;
|
Statement s = null;
|
||||||
try {
|
try {
|
||||||
@@ -547,6 +489,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
if (txn == null) {
|
if (txn == null) {
|
||||||
// Open a new connection
|
// Open a new connection
|
||||||
txn = createConnection();
|
txn = createConnection();
|
||||||
|
if (txn == null) throw new DbException();
|
||||||
txn.setAutoCommit(false);
|
txn.setAutoCommit(false);
|
||||||
connectionsLock.lock();
|
connectionsLock.lock();
|
||||||
try {
|
try {
|
||||||
@@ -1565,7 +1508,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
if (raw == null) throw new MessageDeletedException();
|
if (raw == null) throw new MessageDeletedException();
|
||||||
if (raw.length <= MESSAGE_HEADER_LENGTH) throw new AssertionError();
|
if (raw.length < MESSAGE_HEADER_LENGTH) throw new AssertionError();
|
||||||
byte[] body = new byte[raw.length - MESSAGE_HEADER_LENGTH];
|
byte[] body = new byte[raw.length - MESSAGE_HEADER_LENGTH];
|
||||||
System.arraycopy(raw, MESSAGE_HEADER_LENGTH, body, 0, body.length);
|
System.arraycopy(raw, MESSAGE_HEADER_LENGTH, body, 0, body.length);
|
||||||
return new Message(m, g, timestamp, body);
|
return new Message(m, g, timestamp, body);
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package org.briarproject.bramble.keyagreement;
|
package org.briarproject.bramble.keyagreement;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.FormatException;
|
import org.briarproject.bramble.api.FormatException;
|
||||||
|
import org.briarproject.bramble.api.UnsupportedVersionException;
|
||||||
import org.briarproject.bramble.api.data.BdfList;
|
import org.briarproject.bramble.api.data.BdfList;
|
||||||
import org.briarproject.bramble.api.data.BdfReader;
|
import org.briarproject.bramble.api.data.BdfReader;
|
||||||
import org.briarproject.bramble.api.data.BdfReaderFactory;
|
import org.briarproject.bramble.api.data.BdfReaderFactory;
|
||||||
import org.briarproject.bramble.api.keyagreement.Payload;
|
import org.briarproject.bramble.api.keyagreement.Payload;
|
||||||
import org.briarproject.bramble.api.keyagreement.PayloadParser;
|
import org.briarproject.bramble.api.keyagreement.PayloadParser;
|
||||||
import org.briarproject.bramble.api.keyagreement.TransportDescriptor;
|
import org.briarproject.bramble.api.keyagreement.TransportDescriptor;
|
||||||
import org.briarproject.bramble.api.keyagreement.UnsupportedVersionException;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
||||||
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
||||||
@@ -21,7 +21,6 @@ import java.util.List;
|
|||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.BETA_PROTOCOL_VERSION;
|
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
|
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.PROTOCOL_VERSION;
|
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.PROTOCOL_VERSION;
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
|
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
|
||||||
@@ -44,11 +43,8 @@ class PayloadParserImpl implements PayloadParser {
|
|||||||
// First byte: the protocol version
|
// First byte: the protocol version
|
||||||
int protocolVersion = in.read();
|
int protocolVersion = in.read();
|
||||||
if (protocolVersion == -1) throw new FormatException();
|
if (protocolVersion == -1) throw new FormatException();
|
||||||
if (protocolVersion != PROTOCOL_VERSION) {
|
if (protocolVersion != PROTOCOL_VERSION)
|
||||||
boolean tooOld = protocolVersion < PROTOCOL_VERSION ||
|
throw new UnsupportedVersionException();
|
||||||
protocolVersion == BETA_PROTOCOL_VERSION;
|
|
||||||
throw new UnsupportedVersionException(tooOld);
|
|
||||||
}
|
|
||||||
// The rest of the payload is a BDF list with one or more elements
|
// The rest of the payload is a BDF list with one or more elements
|
||||||
BdfReader r = bdfReaderFactory.createReader(in);
|
BdfReader r = bdfReaderFactory.createReader(in);
|
||||||
BdfList payload = r.readList();
|
BdfList payload = r.readList();
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import javax.inject.Inject;
|
|||||||
import static java.util.logging.Level.FINE;
|
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.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.COMPACTING_DATABASE;
|
|
||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE;
|
||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.RUNNING;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.RUNNING;
|
||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING;
|
||||||
@@ -160,17 +159,11 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDatabaseMigration() {
|
public void onMigrationRun() {
|
||||||
state = MIGRATING_DATABASE;
|
state = MIGRATING_DATABASE;
|
||||||
eventBus.broadcast(new LifecycleEvent(MIGRATING_DATABASE));
|
eventBus.broadcast(new LifecycleEvent(MIGRATING_DATABASE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDatabaseCompaction() {
|
|
||||||
state = COMPACTING_DATABASE;
|
|
||||||
eventBus.broadcast(new LifecycleEvent(COMPACTING_DATABASE));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stopServices() {
|
public void stopServices() {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import org.briarproject.bramble.api.system.Clock;
|
|||||||
import org.briarproject.bramble.api.system.LocationUtils;
|
import org.briarproject.bramble.api.system.LocationUtils;
|
||||||
import org.briarproject.bramble.api.system.ResourceProvider;
|
import org.briarproject.bramble.api.system.ResourceProvider;
|
||||||
import org.briarproject.bramble.util.IoUtils;
|
import org.briarproject.bramble.util.IoUtils;
|
||||||
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
@@ -69,11 +70,9 @@ import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_
|
|||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_NEVER;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_NEVER;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WITH_BRIDGES;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WITH_BRIDGES;
|
||||||
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_V2;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION_V3;
|
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.bramble.util.PrivacyUtils.scrubOnion;
|
import static org.briarproject.bramble.util.PrivacyUtils.scrubOnion;
|
||||||
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -88,8 +87,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
private static final String OWNER = "__OwningControllerProcess";
|
private static final String OWNER = "__OwningControllerProcess";
|
||||||
private static final int COOKIE_TIMEOUT_MS = 3000;
|
private static final int COOKIE_TIMEOUT_MS = 3000;
|
||||||
private static final int COOKIE_POLLING_INTERVAL_MS = 200;
|
private static final int COOKIE_POLLING_INTERVAL_MS = 200;
|
||||||
private static final Pattern ONION_V2 = Pattern.compile("[a-z2-7]{16}");
|
private static final Pattern ONION = Pattern.compile("[a-z2-7]{16}");
|
||||||
private static final Pattern ONION_V3 = Pattern.compile("[a-z2-7]{56}");
|
|
||||||
|
|
||||||
private final Executor ioExecutor, connectionStatusExecutor;
|
private final Executor ioExecutor, connectionStatusExecutor;
|
||||||
private final NetworkManager networkManager;
|
private final NetworkManager networkManager;
|
||||||
@@ -364,7 +362,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
// If there's already a port number stored in config, reuse it
|
// If there's already a port number stored in config, reuse it
|
||||||
String portString = settings.get(PREF_TOR_PORT);
|
String portString = settings.get(PREF_TOR_PORT);
|
||||||
int port;
|
int port;
|
||||||
if (isNullOrEmpty(portString)) port = 0;
|
if (StringUtils.isNullOrEmpty(portString)) port = 0;
|
||||||
else port = Integer.parseInt(portString);
|
else port = Integer.parseInt(portString);
|
||||||
// Bind a server socket to receive connections from Tor
|
// Bind a server socket to receive connections from Tor
|
||||||
ServerSocket ss = null;
|
ServerSocket ss = null;
|
||||||
@@ -429,11 +427,11 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Publish the hidden service's onion hostname in transport properties
|
// Publish the hidden service's onion hostname in transport properties
|
||||||
String onion2 = response.get(HS_ADDRESS);
|
String hostname = response.get(HS_ADDRESS);
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Hidden service " + scrubOnion(onion2));
|
LOG.info("Hidden service " + scrubOnion(hostname));
|
||||||
TransportProperties p = new TransportProperties();
|
TransportProperties p = new TransportProperties();
|
||||||
p.put(PROP_ONION_V2, onion2);
|
p.put(PROP_ONION, hostname);
|
||||||
callback.mergeLocalProperties(p);
|
callback.mergeLocalProperties(p);
|
||||||
if (privKey == null) {
|
if (privKey == null) {
|
||||||
// Save the hidden service's private key for next time
|
// Save the hidden service's private key for next time
|
||||||
@@ -532,41 +530,26 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
@Override
|
@Override
|
||||||
public DuplexTransportConnection createConnection(TransportProperties p) {
|
public DuplexTransportConnection createConnection(TransportProperties p) {
|
||||||
if (!isRunning()) return null;
|
if (!isRunning()) return null;
|
||||||
String bestOnion = null;
|
String onion = p.get(PROP_ONION);
|
||||||
String onion2 = p.get(PROP_ONION_V2);
|
if (StringUtils.isNullOrEmpty(onion)) return null;
|
||||||
String onion3 = p.get(PROP_ONION_V3);
|
if (!ONION.matcher(onion).matches()) {
|
||||||
if (!isNullOrEmpty(onion2)) {
|
// not scrubbing this address, so we are able to find the problem
|
||||||
if (ONION_V2.matcher(onion2).matches()) {
|
if (LOG.isLoggable(INFO)) LOG.info("Invalid hostname: " + onion);
|
||||||
bestOnion = onion2;
|
return null;
|
||||||
} else {
|
|
||||||
// Don't scrub the address so we can find the problem
|
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Invalid v2 hostname: " + onion2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!isNullOrEmpty(onion3)) {
|
|
||||||
if (ONION_V3.matcher(onion3).matches()) {
|
|
||||||
bestOnion = onion3;
|
|
||||||
} else {
|
|
||||||
// Don't scrub the address so we can find the problem
|
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Invalid v3 hostname: " + onion3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (bestOnion == null) return null;
|
|
||||||
Socket s = null;
|
Socket s = null;
|
||||||
try {
|
try {
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Connecting to " + scrubOnion(bestOnion));
|
LOG.info("Connecting to " + scrubOnion(onion));
|
||||||
s = torSocketFactory.createSocket(bestOnion + ".onion", 80);
|
s = torSocketFactory.createSocket(onion + ".onion", 80);
|
||||||
s.setSoTimeout(socketTimeout);
|
s.setSoTimeout(socketTimeout);
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Connected to " + scrubOnion(bestOnion));
|
LOG.info("Connected to " + scrubOnion(onion));
|
||||||
return new TorTransportConnection(this, s);
|
return new TorTransportConnection(this, s);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(INFO)) {
|
if (LOG.isLoggable(INFO)) {
|
||||||
LOG.info("Could not connect to " + scrubOnion(bestOnion)
|
LOG.info("Could not connect to " + scrubOnion(onion) + ": " +
|
||||||
+ ": " + e.toString());
|
e.toString());
|
||||||
}
|
}
|
||||||
tryToClose(s);
|
tryToClose(s);
|
||||||
return null;
|
return null;
|
||||||
@@ -644,9 +627,6 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
if (s.getNamespace().equals(ID.getString())) {
|
if (s.getNamespace().equals(ID.getString())) {
|
||||||
LOG.info("Tor settings updated");
|
LOG.info("Tor settings updated");
|
||||||
settings = s.getSettings();
|
settings = s.getSettings();
|
||||||
// Works around a bug introduced in Tor 0.3.4.8. Could be
|
|
||||||
// replaced with callback.transportDisabled() when fixed.
|
|
||||||
disableNetwork();
|
|
||||||
updateConnectionStatus(networkManager.getNetworkStatus());
|
updateConnectionStatus(networkManager.getNetworkStatus());
|
||||||
}
|
}
|
||||||
} else if (e instanceof NetworkStatusEvent) {
|
} else if (e instanceof NetworkStatusEvent) {
|
||||||
@@ -654,16 +634,6 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void disableNetwork() {
|
|
||||||
connectionStatusExecutor.execute(() -> {
|
|
||||||
try {
|
|
||||||
enableNetwork(false);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
logException(LOG, WARNING, ex);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateConnectionStatus(NetworkStatus status) {
|
private void updateConnectionStatus(NetworkStatus status) {
|
||||||
connectionStatusExecutor.execute(() -> {
|
connectionStatusExecutor.execute(() -> {
|
||||||
if (!running) return;
|
if (!running) return;
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ class MessageFactoryImpl implements MessageFactory {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Message createMessage(GroupId g, long timestamp, byte[] body) {
|
public Message createMessage(GroupId g, long timestamp, byte[] body) {
|
||||||
if (body.length == 0) throw new IllegalArgumentException();
|
|
||||||
if (body.length > MAX_MESSAGE_BODY_LENGTH)
|
if (body.length > MAX_MESSAGE_BODY_LENGTH)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
MessageId id = getMessageId(g, timestamp, body);
|
MessageId id = getMessageId(g, timestamp, body);
|
||||||
@@ -55,7 +54,7 @@ class MessageFactoryImpl implements MessageFactory {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Message createMessage(byte[] raw) {
|
public Message createMessage(byte[] raw) {
|
||||||
if (raw.length <= MESSAGE_HEADER_LENGTH)
|
if (raw.length < MESSAGE_HEADER_LENGTH)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
if (raw.length > MAX_MESSAGE_LENGTH)
|
if (raw.length > MAX_MESSAGE_LENGTH)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
|
|||||||
@@ -124,8 +124,7 @@ class SyncRecordReaderImpl implements SyncRecordReader {
|
|||||||
if (!hasMessage()) throw new FormatException();
|
if (!hasMessage()) throw new FormatException();
|
||||||
if (nextRecord == null) throw new AssertionError();
|
if (nextRecord == null) throw new AssertionError();
|
||||||
byte[] payload = nextRecord.getPayload();
|
byte[] payload = nextRecord.getPayload();
|
||||||
if (payload.length <= MESSAGE_HEADER_LENGTH)
|
if (payload.length < MESSAGE_HEADER_LENGTH) throw new FormatException();
|
||||||
throw new FormatException();
|
|
||||||
// Validate timestamp
|
// Validate timestamp
|
||||||
long timestamp = ByteUtils.readUint64(payload, UniqueId.LENGTH);
|
long timestamp = ByteUtils.readUint64(payload, UniqueId.LENGTH);
|
||||||
if (timestamp < 0) throw new FormatException();
|
if (timestamp < 0) throw new FormatException();
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ Bridge 131.252.210.150:8081 0E858AC201BF0F3FA3C462F64844CBFFC7297A42
|
|||||||
Bridge 67.205.189.122:8443 12D64D5D44E20169585E7378580C0D33A872AD98
|
Bridge 67.205.189.122:8443 12D64D5D44E20169585E7378580C0D33A872AD98
|
||||||
Bridge 45.32.148.146:8443 0CE016FB2462D8BF179AE71F7D702D09DEAC3F1D
|
Bridge 45.32.148.146:8443 0CE016FB2462D8BF179AE71F7D702D09DEAC3F1D
|
||||||
Bridge 148.251.90.59:7510 019F727CA6DCA6CA5C90B55E477B7D87981E75BC
|
Bridge 148.251.90.59:7510 019F727CA6DCA6CA5C90B55E477B7D87981E75BC
|
||||||
|
Bridge 195.91.239.8:9001 BA83F62551545655BBEBBFF353A45438D73FD45A
|
||||||
Bridge 45.55.1.74:8443 6F18FEFBB0CAECD5ABA755312FCCB34FC11A7AB8
|
Bridge 45.55.1.74:8443 6F18FEFBB0CAECD5ABA755312FCCB34FC11A7AB8
|
||||||
Bridge 85.229.131.78:444 50E433CCC5FEC11CC34CB4D92033561E065EA106
|
Bridge 97.107.131.168:65341 DCDA8A5F1E2C50A6756A58462E5CF4B6B2DFDE26
|
||||||
Bridge 178.62.62.193:8443 391B1F9B6A28A1C5FAE1872283985F975E5DB029
|
Bridge 85.229.131.78:444 50E433CCC5FEC11CC34CB4D92033561E065EA106
|
||||||
Bridge 45.76.29.92:8443 ECF1DD51A46FDEF2C50CED992EEEAE8DED18DA0C
|
|
||||||
@@ -79,6 +79,18 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
|
|||||||
assertSame(meta, messageContext.getMetadata());
|
assertSame(meta, messageContext.getMetadata());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = InvalidMessageException.class)
|
||||||
|
public void testRejectsTooShortMessage() throws Exception {
|
||||||
|
Message invalidMessage = getMessage(groupId, 0);
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(clock).currentTimeMillis();
|
||||||
|
will(returnValue(timestamp));
|
||||||
|
}});
|
||||||
|
|
||||||
|
failIfSubclassIsCalled.validateMessage(invalidMessage, group);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAcceptsMinLengthMessage() throws Exception {
|
public void testAcceptsMinLengthMessage() throws Exception {
|
||||||
Message shortMessage = getMessage(groupId, 1);
|
Message shortMessage = getMessage(groupId, 1);
|
||||||
|
|||||||
@@ -26,10 +26,11 @@ import org.briarproject.bramble.api.transport.KeySetId;
|
|||||||
import org.briarproject.bramble.api.transport.OutgoingKeys;
|
import org.briarproject.bramble.api.transport.OutgoingKeys;
|
||||||
import org.briarproject.bramble.api.transport.TransportKeys;
|
import org.briarproject.bramble.api.transport.TransportKeys;
|
||||||
import org.briarproject.bramble.system.SystemClock;
|
import org.briarproject.bramble.system.SystemClock;
|
||||||
|
import org.briarproject.bramble.test.ArrayClock;
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.briarproject.bramble.test.SettableClock;
|
|
||||||
import org.briarproject.bramble.test.TestDatabaseConfig;
|
import org.briarproject.bramble.test.TestDatabaseConfig;
|
||||||
import org.briarproject.bramble.test.TestMessageFactory;
|
import org.briarproject.bramble.test.TestMessageFactory;
|
||||||
|
import org.briarproject.bramble.test.TestUtils;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -45,7 +46,6 @@ import java.util.Map.Entry;
|
|||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
|
|
||||||
import static java.util.Collections.emptyList;
|
import static java.util.Collections.emptyList;
|
||||||
import static java.util.Collections.emptyMap;
|
import static java.util.Collections.emptyMap;
|
||||||
@@ -61,9 +61,6 @@ import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERE
|
|||||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID;
|
||||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
|
||||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
|
||||||
import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
|
|
||||||
import static org.briarproject.bramble.db.DatabaseConstants.LAST_COMPACTED_KEY;
|
|
||||||
import static org.briarproject.bramble.db.DatabaseConstants.MAX_COMPACTION_INTERVAL_MS;
|
|
||||||
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getAuthor;
|
import static org.briarproject.bramble.test.TestUtils.getAuthor;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getClientId;
|
import static org.briarproject.bramble.test.TestUtils.getClientId;
|
||||||
@@ -1821,9 +1818,10 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testMessageRetransmission() throws Exception {
|
public void testMessageRetransmission() throws Exception {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
AtomicLong time = new AtomicLong(now);
|
long steps[] = {now, now, now + MAX_LATENCY * 2 - 1,
|
||||||
|
now + MAX_LATENCY * 2};
|
||||||
Database<Connection> db =
|
Database<Connection> db =
|
||||||
open(false, new TestMessageFactory(), new SettableClock(time));
|
open(false, new TestMessageFactory(), new ArrayClock(steps));
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, a shared group and a shared message
|
// Add a contact, a shared group and a shared message
|
||||||
@@ -1849,13 +1847,11 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
|
|
||||||
// Time: now + MAX_LATENCY * 2 - 1
|
// Time: now + MAX_LATENCY * 2 - 1
|
||||||
// The message should not yet be sendable
|
// The message should not yet be sendable
|
||||||
time.set(now + MAX_LATENCY * 2 - 1);
|
|
||||||
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE, MAX_LATENCY);
|
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE, MAX_LATENCY);
|
||||||
assertTrue(ids.isEmpty());
|
assertTrue(ids.isEmpty());
|
||||||
|
|
||||||
// Time: now + MAX_LATENCY * 2
|
// Time: now + MAX_LATENCY * 2
|
||||||
// The message should have expired and should now be sendable
|
// The message should have expired and should now be sendable
|
||||||
time.set(now + MAX_LATENCY * 2);
|
|
||||||
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE, MAX_LATENCY);
|
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE, MAX_LATENCY);
|
||||||
assertEquals(singletonList(messageId), ids);
|
assertEquals(singletonList(messageId), ids);
|
||||||
|
|
||||||
@@ -1863,12 +1859,13 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFasterMessageRetransmission() throws Exception {
|
public void testFasterMessageRetransmission() throws Exception {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
AtomicLong time = new AtomicLong(now);
|
long steps[] = {now, now, now, now, now + 1};
|
||||||
Database<Connection> db =
|
Database<Connection> db =
|
||||||
open(false, new TestMessageFactory(), new SettableClock(time));
|
open(false, new TestMessageFactory(), new ArrayClock(steps));
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Add a contact, a shared group and a shared message
|
// Add a contact, a shared group and a shared message
|
||||||
@@ -1906,7 +1903,6 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
// Time: now + 1
|
// Time: now + 1
|
||||||
// The message should no longer be sendable via the faster transport,
|
// The message should no longer be sendable via the faster transport,
|
||||||
// as the ETA is now equal
|
// as the ETA is now equal
|
||||||
time.set(now + 1);
|
|
||||||
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE,
|
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE,
|
||||||
MAX_LATENCY - 1);
|
MAX_LATENCY - 1);
|
||||||
assertTrue(ids.isEmpty());
|
assertTrue(ids.isEmpty());
|
||||||
@@ -1915,45 +1911,6 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCompactionTime() throws Exception {
|
|
||||||
MessageFactory messageFactory = new TestMessageFactory();
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
AtomicLong time = new AtomicLong(now);
|
|
||||||
Clock clock = new SettableClock(time);
|
|
||||||
|
|
||||||
// Time: now
|
|
||||||
// The last compaction time should be initialised to the current time
|
|
||||||
Database<Connection> db = open(false, messageFactory, clock);
|
|
||||||
Connection txn = db.startTransaction();
|
|
||||||
Settings s = db.getSettings(txn, DB_SETTINGS_NAMESPACE);
|
|
||||||
assertEquals(now, s.getLong(LAST_COMPACTED_KEY, 0));
|
|
||||||
db.commitTransaction(txn);
|
|
||||||
db.close();
|
|
||||||
|
|
||||||
// Time: now + MAX_COMPACTION_INTERVAL_MS
|
|
||||||
// The DB should not be compacted, so the last compaction time should
|
|
||||||
// not be updated
|
|
||||||
time.set(now + MAX_COMPACTION_INTERVAL_MS);
|
|
||||||
db = open(true, messageFactory, clock);
|
|
||||||
txn = db.startTransaction();
|
|
||||||
s = db.getSettings(txn, DB_SETTINGS_NAMESPACE);
|
|
||||||
assertEquals(now, s.getLong(LAST_COMPACTED_KEY, 0));
|
|
||||||
db.commitTransaction(txn);
|
|
||||||
db.close();
|
|
||||||
|
|
||||||
// Time: now + MAX_COMPACTION_INTERVAL_MS + 1
|
|
||||||
// The DB should be compacted, so the last compaction time should be
|
|
||||||
// updated
|
|
||||||
time.set(now + MAX_COMPACTION_INTERVAL_MS + 1);
|
|
||||||
db = open(true, messageFactory, clock);
|
|
||||||
txn = db.startTransaction();
|
|
||||||
s = db.getSettings(txn, DB_SETTINGS_NAMESPACE);
|
|
||||||
assertEquals(now + MAX_COMPACTION_INTERVAL_MS + 1,
|
|
||||||
s.getLong(LAST_COMPACTED_KEY, 0));
|
|
||||||
db.commitTransaction(txn);
|
|
||||||
db.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
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());
|
||||||
@@ -1964,7 +1921,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
Database<Connection> db =
|
Database<Connection> db =
|
||||||
createDatabase(new TestDatabaseConfig(testDir, MAX_SIZE),
|
createDatabase(new TestDatabaseConfig(testDir, MAX_SIZE),
|
||||||
messageFactory, clock);
|
messageFactory, clock);
|
||||||
if (!resume) deleteTestDirectory(testDir);
|
if (!resume) TestUtils.deleteTestDirectory(testDir);
|
||||||
db.open(key, null);
|
db.open(key, null);
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,156 +0,0 @@
|
|||||||
package org.briarproject.bramble.keyagreement;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.Bytes;
|
|
||||||
import org.briarproject.bramble.api.FormatException;
|
|
||||||
import org.briarproject.bramble.api.data.BdfList;
|
|
||||||
import org.briarproject.bramble.api.data.BdfReader;
|
|
||||||
import org.briarproject.bramble.api.data.BdfReaderFactory;
|
|
||||||
import org.briarproject.bramble.api.keyagreement.Payload;
|
|
||||||
import org.briarproject.bramble.api.keyagreement.UnsupportedVersionException;
|
|
||||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
|
||||||
import org.jmock.Expectations;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
|
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.BETA_PROTOCOL_VERSION;
|
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
|
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.PROTOCOL_VERSION;
|
|
||||||
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
public class PayloadParserImplTest extends BrambleMockTestCase {
|
|
||||||
|
|
||||||
private final BdfReaderFactory bdfReaderFactory =
|
|
||||||
context.mock(BdfReaderFactory.class);
|
|
||||||
private final BdfReader bdfReader = context.mock(BdfReader.class);
|
|
||||||
|
|
||||||
private final PayloadParserImpl payloadParser =
|
|
||||||
new PayloadParserImpl(bdfReaderFactory);
|
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
|
||||||
public void testThrowsFormatExceptionIfPayloadIsEmpty() throws Exception {
|
|
||||||
payloadParser.parse(new byte[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testThrowsUnsupportedVersionExceptionForOldVersion()
|
|
||||||
throws Exception {
|
|
||||||
try {
|
|
||||||
payloadParser.parse(new byte[] {PROTOCOL_VERSION - 1});
|
|
||||||
fail();
|
|
||||||
} catch (UnsupportedVersionException e) {
|
|
||||||
assertTrue(e.isTooOld());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testThrowsUnsupportedVersionExceptionForBetaVersion()
|
|
||||||
throws Exception {
|
|
||||||
try {
|
|
||||||
payloadParser.parse(new byte[] {BETA_PROTOCOL_VERSION});
|
|
||||||
fail();
|
|
||||||
} catch (UnsupportedVersionException e) {
|
|
||||||
assertTrue(e.isTooOld());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testThrowsUnsupportedVersionExceptionForNewVersion()
|
|
||||||
throws Exception {
|
|
||||||
try {
|
|
||||||
payloadParser.parse(new byte[] {PROTOCOL_VERSION + 1});
|
|
||||||
fail();
|
|
||||||
} catch (UnsupportedVersionException e) {
|
|
||||||
assertFalse(e.isTooOld());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
|
||||||
public void testThrowsFormatExceptionForEmptyList() throws Exception {
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
oneOf(bdfReaderFactory).createReader(
|
|
||||||
with(any(ByteArrayInputStream.class)));
|
|
||||||
will(returnValue(bdfReader));
|
|
||||||
oneOf(bdfReader).readList();
|
|
||||||
will(returnValue(new BdfList()));
|
|
||||||
}});
|
|
||||||
|
|
||||||
payloadParser.parse(new byte[] {PROTOCOL_VERSION});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
|
||||||
public void testThrowsFormatExceptionForDataAfterList()
|
|
||||||
throws Exception {
|
|
||||||
byte[] commitment = getRandomBytes(COMMIT_LENGTH);
|
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
oneOf(bdfReaderFactory).createReader(
|
|
||||||
with(any(ByteArrayInputStream.class)));
|
|
||||||
will(returnValue(bdfReader));
|
|
||||||
oneOf(bdfReader).readList();
|
|
||||||
will(returnValue(BdfList.of(new Bytes(commitment))));
|
|
||||||
oneOf(bdfReader).eof();
|
|
||||||
will(returnValue(false));
|
|
||||||
}});
|
|
||||||
|
|
||||||
payloadParser.parse(new byte[] {PROTOCOL_VERSION});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
|
||||||
public void testThrowsFormatExceptionForShortCommitment()
|
|
||||||
throws Exception {
|
|
||||||
byte[] commitment = getRandomBytes(COMMIT_LENGTH - 1);
|
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
oneOf(bdfReaderFactory).createReader(
|
|
||||||
with(any(ByteArrayInputStream.class)));
|
|
||||||
will(returnValue(bdfReader));
|
|
||||||
oneOf(bdfReader).readList();
|
|
||||||
will(returnValue(BdfList.of(new Bytes(commitment))));
|
|
||||||
oneOf(bdfReader).eof();
|
|
||||||
will(returnValue(true));
|
|
||||||
}});
|
|
||||||
|
|
||||||
payloadParser.parse(new byte[] {PROTOCOL_VERSION});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
|
||||||
public void testThrowsFormatExceptionForLongCommitment()
|
|
||||||
throws Exception {
|
|
||||||
byte[] commitment = getRandomBytes(COMMIT_LENGTH + 1);
|
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
oneOf(bdfReaderFactory).createReader(
|
|
||||||
with(any(ByteArrayInputStream.class)));
|
|
||||||
will(returnValue(bdfReader));
|
|
||||||
oneOf(bdfReader).readList();
|
|
||||||
will(returnValue(BdfList.of(new Bytes(commitment))));
|
|
||||||
oneOf(bdfReader).eof();
|
|
||||||
will(returnValue(true));
|
|
||||||
}});
|
|
||||||
|
|
||||||
payloadParser.parse(new byte[] {PROTOCOL_VERSION});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAcceptsPayloadWithNoDescriptors() throws Exception {
|
|
||||||
byte[] commitment = getRandomBytes(COMMIT_LENGTH);
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
oneOf(bdfReaderFactory).createReader(
|
|
||||||
with(any(ByteArrayInputStream.class)));
|
|
||||||
will(returnValue(bdfReader));
|
|
||||||
oneOf(bdfReader).readList();
|
|
||||||
will(returnValue(BdfList.of(new Bytes(commitment))));
|
|
||||||
oneOf(bdfReader).eof();
|
|
||||||
will(returnValue(true));
|
|
||||||
}});
|
|
||||||
|
|
||||||
Payload p = payloadParser.parse(new byte[] {PROTOCOL_VERSION});
|
|
||||||
assertArrayEquals(commitment, p.getCommitment());
|
|
||||||
assertTrue(p.getTransportDescriptors().isEmpty());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -28,6 +28,6 @@ dependencyVerification {
|
|||||||
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
|
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
|
||||||
'org.ow2.asm:asm-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d',
|
'org.ow2.asm:asm-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d',
|
||||||
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
|
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
|
||||||
'org.whispersystems:curve25519-java:0.5.0:curve25519-java-0.5.0.jar:0aadd43cf01d11e9b58f867b3c4f25c3194e8b0623d1953d32dfbfbee009e38d',
|
'org.whispersystems:curve25519-java:0.4.1:curve25519-java-0.4.1.jar:7dd659d8822c06c3aea1a47f18fac9e5761e29cab8100030b877db445005f03e',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ configurations {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation project(path: ':bramble-core', configuration: 'default')
|
implementation project(path: ':bramble-core', configuration: 'default')
|
||||||
implementation fileTree(dir: 'libs', include: '*.jar')
|
implementation fileTree(dir: 'libs', include: '*.jar')
|
||||||
implementation 'net.java.dev.jna:jna:4.5.2'
|
implementation 'net.java.dev.jna:jna:4.4.0'
|
||||||
implementation 'net.java.dev.jna:jna-platform:4.5.2'
|
implementation 'net.java.dev.jna:jna-platform:4.4.0'
|
||||||
tor 'org.briarproject:tor:0.3.4.8@zip'
|
tor 'org.briarproject:tor:0.2.9.16@zip'
|
||||||
|
|
||||||
apt 'com.google.dagger:dagger-compiler:2.0.2'
|
apt 'com.google.dagger:dagger-compiler:2.0.2'
|
||||||
|
|
||||||
|
|||||||
@@ -10,13 +10,9 @@ import org.briarproject.bramble.api.system.ResourceProvider;
|
|||||||
import org.briarproject.bramble.test.BrambleJavaIntegrationTestComponent;
|
import org.briarproject.bramble.test.BrambleJavaIntegrationTestComponent;
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.briarproject.bramble.test.DaggerBrambleJavaIntegrationTestComponent;
|
import org.briarproject.bramble.test.DaggerBrambleJavaIntegrationTestComponent;
|
||||||
import org.briarproject.bramble.util.OsUtils;
|
import org.junit.AfterClass;
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.Parameterized;
|
|
||||||
import org.junit.runners.Parameterized.Parameters;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -33,20 +29,13 @@ import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
|||||||
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
|
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
|
||||||
import static org.briarproject.bramble.test.TestUtils.isOptionalTestEnabled;
|
import static org.briarproject.bramble.test.TestUtils.isOptionalTestEnabled;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
import static org.junit.Assume.assumeTrue;
|
import static org.junit.Assume.assumeTrue;
|
||||||
|
|
||||||
@RunWith(Parameterized.class)
|
|
||||||
public class BridgeTest extends BrambleTestCase {
|
public class BridgeTest extends BrambleTestCase {
|
||||||
|
|
||||||
@Parameters
|
private final static long TIMEOUT = SECONDS.toMillis(23);
|
||||||
public static Iterable<String> data() {
|
|
||||||
BrambleJavaIntegrationTestComponent component =
|
|
||||||
DaggerBrambleJavaIntegrationTestComponent.builder().build();
|
|
||||||
return component.getCircumventionProvider().getBridges();
|
|
||||||
}
|
|
||||||
|
|
||||||
private final static long TIMEOUT = SECONDS.toMillis(30);
|
|
||||||
|
|
||||||
private final static Logger LOG =
|
private final static Logger LOG =
|
||||||
Logger.getLogger(BridgeTest.class.getName());
|
Logger.getLogger(BridgeTest.class.getName());
|
||||||
@@ -64,23 +53,17 @@ public class BridgeTest extends BrambleTestCase {
|
|||||||
@Inject
|
@Inject
|
||||||
Clock clock;
|
Clock clock;
|
||||||
|
|
||||||
private final File torDir = getTestDirectory();
|
private List<String> bridges;
|
||||||
private final String bridge;
|
|
||||||
|
|
||||||
private LinuxTorPluginFactory factory;
|
private LinuxTorPluginFactory factory;
|
||||||
|
private final static File torDir = getTestDirectory();
|
||||||
|
|
||||||
public BridgeTest(String bridge) {
|
private volatile String currentBridge = null;
|
||||||
this.bridge = bridge;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
// Skip this test unless it's explicitly enabled in the environment
|
// Skip this test unless it's explicitly enabled in the environment
|
||||||
assumeTrue(isOptionalTestEnabled(BridgeTest.class));
|
assumeTrue(isOptionalTestEnabled(BridgeTest.class));
|
||||||
|
|
||||||
// TODO: Remove this assumption when the plugin supports other platforms
|
|
||||||
assumeTrue(OsUtils.isLinux());
|
|
||||||
|
|
||||||
BrambleJavaIntegrationTestComponent component =
|
BrambleJavaIntegrationTestComponent component =
|
||||||
DaggerBrambleJavaIntegrationTestComponent.builder().build();
|
DaggerBrambleJavaIntegrationTestComponent.builder().build();
|
||||||
component.inject(this);
|
component.inject(this);
|
||||||
@@ -89,6 +72,7 @@ public class BridgeTest extends BrambleTestCase {
|
|||||||
LocationUtils locationUtils = () -> "US";
|
LocationUtils locationUtils = () -> "US";
|
||||||
SocketFactory torSocketFactory = SocketFactory.getDefault();
|
SocketFactory torSocketFactory = SocketFactory.getDefault();
|
||||||
|
|
||||||
|
bridges = circumventionProvider.getBridges();
|
||||||
CircumventionProvider bridgeProvider = new CircumventionProvider() {
|
CircumventionProvider bridgeProvider = new CircumventionProvider() {
|
||||||
@Override
|
@Override
|
||||||
public boolean isTorProbablyBlocked(String countryCode) {
|
public boolean isTorProbablyBlocked(String countryCode) {
|
||||||
@@ -102,7 +86,7 @@ public class BridgeTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getBridges() {
|
public List<String> getBridges() {
|
||||||
return singletonList(bridge);
|
return singletonList(currentBridge);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
factory = new LinuxTorPluginFactory(ioExecutor, networkManager,
|
factory = new LinuxTorPluginFactory(ioExecutor, networkManager,
|
||||||
@@ -110,18 +94,25 @@ public class BridgeTest extends BrambleTestCase {
|
|||||||
resourceProvider, bridgeProvider, clock, torDir);
|
resourceProvider, bridgeProvider, clock, torDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@AfterClass
|
||||||
public void tearDown() {
|
public static void tearDown() {
|
||||||
deleteTestDirectory(torDir);
|
deleteTestDirectory(torDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBridges() throws Exception {
|
public void testBridges() throws Exception {
|
||||||
|
assertTrue(bridges.size() > 0);
|
||||||
|
|
||||||
|
for (String bridge : bridges) testBridge(bridge);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testBridge(String bridge) throws Exception {
|
||||||
DuplexPlugin duplexPlugin =
|
DuplexPlugin duplexPlugin =
|
||||||
factory.createPlugin(new TorPluginCallBack());
|
factory.createPlugin(new TorPluginCallBack());
|
||||||
assertNotNull(duplexPlugin);
|
assertNotNull(duplexPlugin);
|
||||||
LinuxTorPlugin plugin = (LinuxTorPlugin) duplexPlugin;
|
LinuxTorPlugin plugin = (LinuxTorPlugin) duplexPlugin;
|
||||||
|
|
||||||
|
currentBridge = bridge;
|
||||||
LOG.warning("Testing " + bridge);
|
LOG.warning("Testing " + bridge);
|
||||||
try {
|
try {
|
||||||
plugin.start();
|
plugin.start();
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import org.briarproject.bramble.BrambleJavaModule;
|
|||||||
import org.briarproject.bramble.event.EventModule;
|
import org.briarproject.bramble.event.EventModule;
|
||||||
import org.briarproject.bramble.plugin.PluginModule;
|
import org.briarproject.bramble.plugin.PluginModule;
|
||||||
import org.briarproject.bramble.plugin.tor.BridgeTest;
|
import org.briarproject.bramble.plugin.tor.BridgeTest;
|
||||||
import org.briarproject.bramble.plugin.tor.CircumventionProvider;
|
|
||||||
import org.briarproject.bramble.system.SystemModule;
|
import org.briarproject.bramble.system.SystemModule;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
@@ -23,5 +22,4 @@ public interface BrambleJavaIntegrationTestComponent {
|
|||||||
|
|
||||||
void inject(BridgeTest init);
|
void inject(BridgeTest init);
|
||||||
|
|
||||||
CircumventionProvider getCircumventionProvider();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ dependencyVerification {
|
|||||||
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
||||||
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||||
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
|
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
|
||||||
'net.java.dev.jna:jna-platform:4.5.2:jna-platform-4.5.2.jar:f1d00c167d8921c6e23c626ef9f1c3ae0be473c95c68ffa012bc7ae55a87e2d6',
|
'net.java.dev.jna:jna-platform:4.4.0:jna-platform-4.4.0.jar:e9dda9e884fc107eb6367710540789a12dfa8ad28be9326b22ca6e352e325499',
|
||||||
'net.java.dev.jna:jna:4.5.2:jna-4.5.2.jar:0c8eb7acf67261656d79005191debaba3b6bf5dd60a43735a245429381dbecff',
|
'net.java.dev.jna:jna:4.4.0:jna-4.4.0.jar:c4dadeeecaa90c8847902082aee5eb107fcf59c5d0e63a17fcaf273c0e2d2bd1',
|
||||||
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
||||||
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
|
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
|
||||||
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
|
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
|
||||||
'org.briarproject:tor:0.3.4.8:tor-0.3.4.8.zip:bc0158c34002f471a4fe14a6a481816c918eb520a220bb027f64be902beb757f',
|
'org.briarproject:tor:0.2.9.16:tor-0.2.9.16.zip:f33091ba414d6a952263981d9059b3d0a9093fd277ae887b3cdd02e8f1936558',
|
||||||
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
|
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
|
||||||
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
|
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
|
||||||
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
|
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
|
||||||
|
|||||||
@@ -17,13 +17,13 @@ def getStdout = { command, defaultValue ->
|
|||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 28
|
compileSdkVersion 28
|
||||||
buildToolsVersion '28.0.3'
|
buildToolsVersion '28.0.2'
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 15
|
minSdkVersion 15
|
||||||
targetSdkVersion 26
|
targetSdkVersion 26
|
||||||
versionCode 10103
|
versionCode 10101
|
||||||
versionName "1.1.3"
|
versionName "1.1.1"
|
||||||
applicationId "org.briarproject.briar.android"
|
applicationId "org.briarproject.briar.android"
|
||||||
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')}\""
|
||||||
@@ -90,7 +90,7 @@ dependencies {
|
|||||||
implementation project(path: ':bramble-core', configuration: 'default')
|
implementation project(path: ':bramble-core', configuration: 'default')
|
||||||
implementation project(':bramble-android')
|
implementation project(':bramble-android')
|
||||||
|
|
||||||
def supportVersion = '28.0.0'
|
def supportVersion = '27.1.1'
|
||||||
implementation "com.android.support:support-v4:$supportVersion"
|
implementation "com.android.support:support-v4:$supportVersion"
|
||||||
implementation("com.android.support:appcompat-v7:$supportVersion") {
|
implementation("com.android.support:appcompat-v7:$supportVersion") {
|
||||||
exclude module: 'support-v4'
|
exclude module: 'support-v4'
|
||||||
@@ -104,17 +104,17 @@ dependencies {
|
|||||||
}
|
}
|
||||||
implementation "com.android.support:cardview-v7:$supportVersion"
|
implementation "com.android.support:cardview-v7:$supportVersion"
|
||||||
implementation "com.android.support:support-annotations:$supportVersion"
|
implementation "com.android.support:support-annotations:$supportVersion"
|
||||||
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
|
||||||
|
|
||||||
implementation('ch.acra:acra:4.11') {
|
implementation('ch.acra:acra:4.9.1') {
|
||||||
exclude module: 'support-v4'
|
exclude module: 'support-v4'
|
||||||
exclude module: 'support-annotations'
|
exclude module: 'support-annotations'
|
||||||
}
|
}
|
||||||
implementation 'info.guardianproject.panic:panic:0.5'
|
implementation 'info.guardianproject.panic:panic:0.5'
|
||||||
implementation 'info.guardianproject.trustedintents:trustedintents:0.2'
|
implementation 'info.guardianproject.trustedintents:trustedintents:0.2'
|
||||||
implementation 'de.hdodenhof:circleimageview:2.2.0'
|
implementation 'de.hdodenhof:circleimageview:2.2.0'
|
||||||
implementation 'com.google.zxing:core:3.3.3'
|
implementation 'com.google.zxing:core:3.3.0'
|
||||||
implementation 'uk.co.samuelwall:material-tap-target-prompt:2.12.4'
|
implementation 'uk.co.samuelwall:material-tap-target-prompt:2.8.0'
|
||||||
implementation 'com.vanniktech:emoji-google:0.5.1'
|
implementation 'com.vanniktech:emoji-google:0.5.1'
|
||||||
|
|
||||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
|
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
|
||||||
@@ -140,6 +140,9 @@ dependencies {
|
|||||||
androidTestAnnotationProcessor "com.google.dagger:dagger-compiler:2.0.2"
|
androidTestAnnotationProcessor "com.google.dagger:dagger-compiler:2.0.2"
|
||||||
androidTestCompileOnly 'javax.annotation:jsr250-api:1.0'
|
androidTestCompileOnly 'javax.annotation:jsr250-api:1.0'
|
||||||
androidTestImplementation 'junit:junit:4.12'
|
androidTestImplementation 'junit:junit:4.12'
|
||||||
|
|
||||||
|
androidTestScreenshotImplementation project(path: ':bramble-api', configuration: 'testOutput')
|
||||||
|
androidTestScreenshotImplementation project(path: ':bramble-core', configuration: 'testOutput')
|
||||||
androidTestScreenshotImplementation "tools.fastlane:screengrab:1.2.0"
|
androidTestScreenshotImplementation "tools.fastlane:screengrab:1.2.0"
|
||||||
androidTestScreenshotImplementation "com.android.support.test.uiautomator:uiautomator-v18:2.1.3"
|
androidTestScreenshotImplementation "com.android.support.test.uiautomator:uiautomator-v18:2.1.3"
|
||||||
}
|
}
|
||||||
@@ -153,9 +156,8 @@ task verifyTranslations {
|
|||||||
lc.children().each { value -> translations.add(value.text()) }
|
lc.children().each { value -> translations.add(value.text()) }
|
||||||
|
|
||||||
def folders = ["default", "en-US"]
|
def folders = ["default", "en-US"]
|
||||||
def exceptions = ["values-night", "values-v21", "values-ldrtl"]
|
|
||||||
project.file("src/main/res").eachDir { dir ->
|
project.file("src/main/res").eachDir { dir ->
|
||||||
if (dir.name.startsWith("values-") && !exceptions.contains(dir.name)) {
|
if (dir.name.startsWith("values-") && !dir.name.endsWith("night") && !dir.name.endsWith("v21")) {
|
||||||
folders.add(dir.name.substring(7).replace("-r", "-"))
|
folders.add(dir.name.substring(7).replace("-r", "-"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,6 @@
|
|||||||
-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.conscrypt.Conscrypt
|
|
||||||
|
|
||||||
# HTML sanitiser
|
# HTML sanitiser
|
||||||
-keep class org.jsoup.safety.Whitelist
|
-keep class org.jsoup.safety.Whitelist
|
||||||
@@ -30,3 +28,5 @@
|
|||||||
|
|
||||||
# Emoji
|
# Emoji
|
||||||
-keep class com.vanniktech.emoji.**
|
-keep class com.vanniktech.emoji.**
|
||||||
|
|
||||||
|
-keepclasseswithmembers public class android.support.v7.widget.RecyclerView { *; }
|
||||||
|
|||||||
@@ -13,3 +13,4 @@
|
|||||||
-dontwarn junit.**
|
-dontwarn junit.**
|
||||||
|
|
||||||
-dontwarn org.briarproject.briar.android.**
|
-dontwarn org.briarproject.briar.android.**
|
||||||
|
-dontwarn org.briarproject.bramble.**
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ public class BriarTestComponentApplication extends BriarApplicationImpl {
|
|||||||
@Override
|
@Override
|
||||||
protected AndroidComponent createApplicationComponent() {
|
protected AndroidComponent createApplicationComponent() {
|
||||||
AndroidComponent component = DaggerBriarUiTestComponent.builder()
|
AndroidComponent component = DaggerBriarUiTestComponent.builder()
|
||||||
.appModule(new AppModule(this)).build();
|
.testAppModule(new TestAppModule(this)).build();
|
||||||
// We need to load the eager singletons directly after making the
|
// We need to load the eager singletons directly after making the
|
||||||
// dependency graphs
|
// dependency graphs
|
||||||
BrambleCoreModule.initEagerSingletons(component);
|
BrambleCoreModule.initEagerSingletons(component);
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ public abstract class UiTest {
|
|||||||
getTargetContext().getString(R.string.screenshot_alice);
|
getTargetContext().getString(R.string.screenshot_alice);
|
||||||
protected static final String PASSWORD = "123456";
|
protected static final String PASSWORD = "123456";
|
||||||
|
|
||||||
|
protected final BriarUiTestComponent alice;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected AccountManager accountManager;
|
protected AccountManager accountManager;
|
||||||
@Inject
|
@Inject
|
||||||
@@ -30,7 +32,8 @@ public abstract class UiTest {
|
|||||||
BriarTestComponentApplication app =
|
BriarTestComponentApplication app =
|
||||||
(BriarTestComponentApplication) getTargetContext()
|
(BriarTestComponentApplication) getTargetContext()
|
||||||
.getApplicationContext();
|
.getApplicationContext();
|
||||||
inject((BriarUiTestComponent) app.getApplicationComponent());
|
alice = (BriarUiTestComponent) app.getApplicationComponent();
|
||||||
|
inject(alice);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void inject(BriarUiTestComponent component);
|
protected abstract void inject(BriarUiTestComponent component);
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ import dagger.Component;
|
|||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Component(modules = {
|
@Component(modules = {
|
||||||
AppModule.class,
|
TestAppModule.class,
|
||||||
BriarCoreModule.class,
|
BriarCoreModule.class,
|
||||||
BrambleAndroidModule.class,
|
BrambleAndroidModule.class,
|
||||||
BriarAccountModule.class,
|
BriarAccountModule.class,
|
||||||
BrambleCoreModule.class
|
BrambleCoreModule.class
|
||||||
})
|
})
|
||||||
public interface BriarUiTestComponent extends AndroidComponent {
|
public interface BriarUiTestComponent extends AndroidComponent, FakeDataTestComponent {
|
||||||
|
|
||||||
void inject(SetupDataTest test);
|
void inject(SetupDataTest test);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package org.briarproject.briar.android;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.contact.ContactManager;
|
||||||
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
|
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||||
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
|
import org.briarproject.bramble.api.sync.SyncSessionFactory;
|
||||||
|
import org.briarproject.bramble.api.transport.KeyManager;
|
||||||
|
import org.briarproject.bramble.api.transport.StreamReaderFactory;
|
||||||
|
import org.briarproject.bramble.api.transport.StreamWriterFactory;
|
||||||
|
import org.briarproject.bramble.client.ClientModule;
|
||||||
|
import org.briarproject.bramble.contact.ContactModule;
|
||||||
|
import org.briarproject.bramble.crypto.CryptoModule;
|
||||||
|
import org.briarproject.bramble.data.DataModule;
|
||||||
|
import org.briarproject.bramble.db.DatabaseModule;
|
||||||
|
import org.briarproject.bramble.event.EventModule;
|
||||||
|
import org.briarproject.bramble.identity.IdentityModule;
|
||||||
|
import org.briarproject.bramble.lifecycle.LifecycleModule;
|
||||||
|
import org.briarproject.bramble.record.RecordModule;
|
||||||
|
import org.briarproject.bramble.sync.SyncModule;
|
||||||
|
import org.briarproject.bramble.system.SystemModule;
|
||||||
|
import org.briarproject.bramble.test.TestCryptoExecutorModule;
|
||||||
|
import org.briarproject.bramble.test.TestDatabaseModule;
|
||||||
|
import org.briarproject.bramble.test.TestSecureRandomModule;
|
||||||
|
import org.briarproject.bramble.transport.TransportModule;
|
||||||
|
import org.briarproject.bramble.versioning.VersioningModule;
|
||||||
|
import org.briarproject.briar.api.messaging.MessagingManager;
|
||||||
|
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
|
||||||
|
import org.briarproject.briar.client.BriarClientModule;
|
||||||
|
import org.briarproject.briar.messaging.MessagingModule;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import dagger.Component;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Component(modules = {
|
||||||
|
TestCryptoExecutorModule.class,
|
||||||
|
TestDatabaseModule.class,
|
||||||
|
TestPluginConfigModule.class,
|
||||||
|
TestSecureRandomModule.class,
|
||||||
|
BriarClientModule.class,
|
||||||
|
ClientModule.class,
|
||||||
|
ContactModule.class,
|
||||||
|
CryptoModule.class,
|
||||||
|
DataModule.class,
|
||||||
|
DatabaseModule.class,
|
||||||
|
EventModule.class,
|
||||||
|
IdentityModule.class,
|
||||||
|
LifecycleModule.class,
|
||||||
|
MessagingModule.class,
|
||||||
|
RecordModule.class,
|
||||||
|
SyncModule.class,
|
||||||
|
SystemModule.class,
|
||||||
|
TransportModule.class,
|
||||||
|
VersioningModule.class
|
||||||
|
})
|
||||||
|
interface FakeDataTestComponent {
|
||||||
|
|
||||||
|
void inject(ContactModule.EagerSingletons init);
|
||||||
|
|
||||||
|
void inject(IdentityModule.EagerSingletons init);
|
||||||
|
|
||||||
|
void inject(LifecycleModule.EagerSingletons init);
|
||||||
|
|
||||||
|
void inject(MessagingModule.EagerSingletons init);
|
||||||
|
|
||||||
|
void inject(SyncModule.EagerSingletons init);
|
||||||
|
|
||||||
|
void inject(SystemModule.EagerSingletons init);
|
||||||
|
|
||||||
|
void inject(TransportModule.EagerSingletons init);
|
||||||
|
|
||||||
|
void inject(VersioningModule.EagerSingletons init);
|
||||||
|
|
||||||
|
LifecycleManager getLifecycleManager();
|
||||||
|
|
||||||
|
IdentityManager getIdentityManager();
|
||||||
|
|
||||||
|
ContactManager getContactManager();
|
||||||
|
|
||||||
|
MessagingManager getMessagingManager();
|
||||||
|
|
||||||
|
KeyManager getKeyManager();
|
||||||
|
|
||||||
|
PrivateMessageFactory getPrivateMessageFactory();
|
||||||
|
|
||||||
|
EventBus getEventBus();
|
||||||
|
|
||||||
|
StreamWriterFactory getStreamWriterFactory();
|
||||||
|
|
||||||
|
StreamReaderFactory getStreamReaderFactory();
|
||||||
|
|
||||||
|
SyncSessionFactory getSyncSessionFactory();
|
||||||
|
}
|
||||||
@@ -5,23 +5,59 @@ import android.support.test.runner.AndroidJUnit4;
|
|||||||
import android.support.test.uiautomator.UiDevice;
|
import android.support.test.uiautomator.UiDevice;
|
||||||
import android.support.test.uiautomator.UiObject;
|
import android.support.test.uiautomator.UiObject;
|
||||||
import android.support.test.uiautomator.UiSelector;
|
import android.support.test.uiautomator.UiSelector;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.FormatException;
|
import org.briarproject.bramble.api.FormatException;
|
||||||
import org.briarproject.bramble.api.contact.Contact;
|
import org.briarproject.bramble.api.contact.Contact;
|
||||||
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
|
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||||
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
|
import org.briarproject.bramble.api.sync.SyncSession;
|
||||||
|
import org.briarproject.bramble.api.sync.SyncSessionFactory;
|
||||||
|
import org.briarproject.bramble.api.transport.KeyManager;
|
||||||
|
import org.briarproject.bramble.api.transport.StreamContext;
|
||||||
|
import org.briarproject.bramble.api.transport.StreamReaderFactory;
|
||||||
|
import org.briarproject.bramble.api.transport.StreamWriter;
|
||||||
|
import org.briarproject.bramble.api.transport.StreamWriterFactory;
|
||||||
|
import org.briarproject.bramble.contact.ContactModule;
|
||||||
|
import org.briarproject.bramble.identity.IdentityModule;
|
||||||
|
import org.briarproject.bramble.lifecycle.LifecycleModule;
|
||||||
|
import org.briarproject.bramble.sync.SyncModule;
|
||||||
|
import org.briarproject.bramble.system.SystemModule;
|
||||||
|
import org.briarproject.bramble.test.TestDatabaseModule;
|
||||||
|
import org.briarproject.bramble.test.TestUtils;
|
||||||
|
import org.briarproject.bramble.transport.TransportModule;
|
||||||
|
import org.briarproject.bramble.versioning.VersioningModule;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.login.OpenDatabaseActivity;
|
import org.briarproject.briar.android.login.OpenDatabaseActivity;
|
||||||
import org.briarproject.briar.android.login.SetupActivity;
|
import org.briarproject.briar.android.login.SetupActivity;
|
||||||
|
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
||||||
|
import org.briarproject.briar.api.messaging.MessagingManager;
|
||||||
|
import org.briarproject.briar.api.messaging.PrivateMessage;
|
||||||
|
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
|
||||||
|
import org.briarproject.briar.messaging.MessagingModule;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import static android.content.Context.MODE_PRIVATE;
|
||||||
import static android.support.test.InstrumentationRegistry.getInstrumentation;
|
import static android.support.test.InstrumentationRegistry.getInstrumentation;
|
||||||
import static android.support.test.InstrumentationRegistry.getTargetContext;
|
import static android.support.test.InstrumentationRegistry.getTargetContext;
|
||||||
import static android.support.test.espresso.Espresso.onView;
|
import static android.support.test.espresso.Espresso.onView;
|
||||||
import static android.support.test.espresso.action.ViewActions.click;
|
import static android.support.test.espresso.action.ViewActions.click;
|
||||||
import static android.support.test.espresso.action.ViewActions.typeText;
|
import static android.support.test.espresso.action.ViewActions.typeText;
|
||||||
import static android.support.test.espresso.assertion.ViewAssertions.matches;
|
import static android.support.test.espresso.assertion.ViewAssertions.matches;
|
||||||
|
import static android.support.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition;
|
||||||
import static android.support.test.espresso.intent.Intents.intended;
|
import static android.support.test.espresso.intent.Intents.intended;
|
||||||
import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent;
|
import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent;
|
||||||
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
|
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||||
@@ -30,9 +66,17 @@ import static android.support.test.espresso.matcher.ViewMatchers.withId;
|
|||||||
import static android.support.test.espresso.matcher.ViewMatchers.withText;
|
import static android.support.test.espresso.matcher.ViewMatchers.withText;
|
||||||
import static android.support.test.runner.lifecycle.Stage.PAUSED;
|
import static android.support.test.runner.lifecycle.Stage.PAUSED;
|
||||||
import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
|
import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
|
||||||
|
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||||
|
import static org.briarproject.briar.android.TestPluginConfigModule.MAX_LATENCY;
|
||||||
|
import static org.briarproject.briar.android.TestPluginConfigModule.TRANSPORT_ID;
|
||||||
import static org.briarproject.briar.android.ViewActions.waitForActivity;
|
import static org.briarproject.briar.android.ViewActions.waitForActivity;
|
||||||
import static org.briarproject.briar.android.ViewActions.waitUntilMatches;
|
import static org.briarproject.briar.android.ViewActions.waitUntilMatches;
|
||||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||||
|
import static org.hamcrest.Matchers.allOf;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@@ -48,11 +92,49 @@ public class SetupDataTest extends ScreenshotTest {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private FakeDataTestComponent bob;
|
||||||
|
private final File testDir =
|
||||||
|
getTargetContext().getDir("test", MODE_PRIVATE);
|
||||||
|
private final File bobDir = new File(testDir, "bob");
|
||||||
|
private final SecretKey master = getSecretKey();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void inject(BriarUiTestComponent component) {
|
protected void inject(BriarUiTestComponent component) {
|
||||||
component.inject(this);
|
component.inject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
Log.e("TEST", testDir.getAbsolutePath());
|
||||||
|
Log.e("TEST", "exists: " + testDir.exists());
|
||||||
|
assertTrue(testDir.mkdirs());
|
||||||
|
bob = DaggerFakeDataTestComponent.builder()
|
||||||
|
.testDatabaseModule(new TestDatabaseModule(bobDir)).build();
|
||||||
|
injectEagerSingletons(bob);
|
||||||
|
Log.e("TEST", "built bob");
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
// Stop the lifecycle manager
|
||||||
|
LifecycleManager lifecycleManager = bob.getLifecycleManager();
|
||||||
|
lifecycleManager.stopServices();
|
||||||
|
lifecycleManager.waitForShutdown();
|
||||||
|
|
||||||
|
TestUtils.deleteTestDirectory(testDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void injectEagerSingletons(FakeDataTestComponent component) {
|
||||||
|
component.inject(new ContactModule.EagerSingletons());
|
||||||
|
component.inject(new IdentityModule.EagerSingletons());
|
||||||
|
component.inject(new LifecycleModule.EagerSingletons());
|
||||||
|
component.inject(new MessagingModule.EagerSingletons());
|
||||||
|
component.inject(new SyncModule.EagerSingletons());
|
||||||
|
component.inject(new SystemModule.EagerSingletons());
|
||||||
|
component.inject(new TransportModule.EagerSingletons());
|
||||||
|
component.inject(new VersioningModule.EagerSingletons());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createAccount() throws Exception {
|
public void createAccount() throws Exception {
|
||||||
// Enter username
|
// Enter username
|
||||||
@@ -103,26 +185,132 @@ public class SetupDataTest extends ScreenshotTest {
|
|||||||
|
|
||||||
assertTrue(accountManager.hasDatabaseKey());
|
assertTrue(accountManager.hasDatabaseKey());
|
||||||
|
|
||||||
|
// WIP below
|
||||||
|
|
||||||
|
// wait for OpenDatabaseActivity to go away
|
||||||
|
onView(isRoot())
|
||||||
|
.perform(waitUntilMatches(
|
||||||
|
allOf(withId(R.id.progressBar), not(isDisplayed()))));
|
||||||
lifecycleManager.waitForStartup();
|
lifecycleManager.waitForStartup();
|
||||||
createTestData();
|
intended(hasComponent(NavDrawerActivity.class.getName()));
|
||||||
|
|
||||||
// close expiry warning
|
// close expiry warning
|
||||||
onView(withId(R.id.expiryWarning))
|
|
||||||
.perform(waitUntilMatches(isDisplayed()));
|
|
||||||
onView(withId(R.id.expiryWarningClose))
|
onView(withId(R.id.expiryWarningClose))
|
||||||
.check(matches(isDisplayed()));
|
.check(matches(isDisplayed()));
|
||||||
onView(withId(R.id.expiryWarningClose))
|
onView(withId(R.id.expiryWarningClose))
|
||||||
.perform(click());
|
.perform(click());
|
||||||
|
|
||||||
|
LocalAuthor aliceAuthor = alice.identityManager().getLocalAuthor();
|
||||||
|
|
||||||
|
LocalAuthor bobAuthor = bob.getIdentityManager().createLocalAuthor(
|
||||||
|
getTargetContext().getString(R.string.screenshot_bob));
|
||||||
|
bob.getIdentityManager().registerLocalAuthor(bobAuthor);
|
||||||
|
// Start the lifecycle manager
|
||||||
|
bob.getLifecycleManager().startServices(getSecretKey());
|
||||||
|
bob.getLifecycleManager().waitForStartup();
|
||||||
|
long timestamp = clock.currentTimeMillis();
|
||||||
|
// Bob adds Alice as a contact
|
||||||
|
ContactId aliceContactId = bob.getContactManager()
|
||||||
|
.addContact(aliceAuthor, bobAuthor.getId(), master,
|
||||||
|
timestamp, true, true, true);
|
||||||
|
// Alice adds Bob as a contact
|
||||||
|
ContactId bobContactId = alice.contactManager()
|
||||||
|
.addContact(bobAuthor, aliceAuthor.getId(), master,
|
||||||
|
timestamp, false, true, true);
|
||||||
|
|
||||||
|
// TODO figure out how many messages
|
||||||
|
read(alice, bobContactId, write(bob, aliceContactId));
|
||||||
|
read(bob, aliceContactId, write(alice, bobContactId));
|
||||||
|
read(alice, bobContactId, write(bob, aliceContactId));
|
||||||
|
read(bob, aliceContactId, write(alice, bobContactId));
|
||||||
|
read(alice, bobContactId, write(bob, aliceContactId));
|
||||||
|
read(bob, aliceContactId, write(alice, bobContactId));
|
||||||
|
read(alice, bobContactId, write(bob, aliceContactId));
|
||||||
|
read(bob, aliceContactId, write(alice, bobContactId));
|
||||||
|
read(alice, bobContactId, write(bob, aliceContactId));
|
||||||
|
read(bob, aliceContactId, write(alice, bobContactId));
|
||||||
|
read(alice, bobContactId, write(bob, aliceContactId));
|
||||||
|
read(bob, aliceContactId, write(alice, bobContactId));
|
||||||
|
read(alice, bobContactId, write(bob, aliceContactId));
|
||||||
|
|
||||||
|
sendMessage(bob, aliceContactId);
|
||||||
|
read(alice, bobContactId, write(bob, aliceContactId));
|
||||||
|
|
||||||
|
onView(isRoot())
|
||||||
|
.perform(waitUntilMatches(withText(bobAuthor.getName())));
|
||||||
|
onView(withId(R.id.recyclerView))
|
||||||
|
.perform(actionOnItemAtPosition(0, click()));
|
||||||
|
onView(isRoot())
|
||||||
|
.perform(waitUntilMatches(withText(R.string.screenshot_message_2)));
|
||||||
|
|
||||||
|
assertEquals(1,
|
||||||
|
alice.conversationManager().getGroupCount(bobContactId).getMsgCount());
|
||||||
|
|
||||||
|
Thread.sleep(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createTestData() {
|
private void sendMessage(FakeDataTestComponent device, ContactId contactId)
|
||||||
try {
|
throws Exception {
|
||||||
createTestDataExceptions();
|
// Send Bob a message
|
||||||
} catch (DbException | FormatException e) {
|
MessagingManager messagingManager = device.getMessagingManager();
|
||||||
throw new AssertionError(e);
|
GroupId groupId = messagingManager.getConversationId(contactId);
|
||||||
}
|
PrivateMessageFactory privateMessageFactory =
|
||||||
|
device.getPrivateMessageFactory();
|
||||||
|
PrivateMessage message = privateMessageFactory.createPrivateMessage(
|
||||||
|
groupId, getMinutesAgo(3),
|
||||||
|
getTargetContext().getString(R.string.screenshot_message_2));
|
||||||
|
messagingManager.addLocalMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void read(FakeDataTestComponent device,
|
||||||
|
ContactId contactId, byte[] stream) throws Exception {
|
||||||
|
// Read and recognise the tag
|
||||||
|
ByteArrayInputStream in = new ByteArrayInputStream(stream);
|
||||||
|
byte[] tag = new byte[TAG_LENGTH];
|
||||||
|
int read = in.read(tag);
|
||||||
|
assertEquals(tag.length, read);
|
||||||
|
KeyManager keyManager = device.getKeyManager();
|
||||||
|
StreamContext ctx = keyManager.getStreamContext(TRANSPORT_ID, tag);
|
||||||
|
assertNotNull(ctx);
|
||||||
|
// Create a stream reader
|
||||||
|
StreamReaderFactory streamReaderFactory =
|
||||||
|
device.getStreamReaderFactory();
|
||||||
|
InputStream streamReader = streamReaderFactory.createStreamReader(
|
||||||
|
in, ctx);
|
||||||
|
// Create an incoming sync session
|
||||||
|
SyncSessionFactory syncSessionFactory = device.getSyncSessionFactory();
|
||||||
|
SyncSession session = syncSessionFactory.createIncomingSession(
|
||||||
|
contactId, streamReader);
|
||||||
|
// Read whatever needs to be read
|
||||||
|
session.run();
|
||||||
|
streamReader.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] write(FakeDataTestComponent device,
|
||||||
|
ContactId contactId) throws Exception {
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
// Get a stream context
|
||||||
|
KeyManager keyManager = device.getKeyManager();
|
||||||
|
StreamContext ctx = keyManager.getStreamContext(contactId,
|
||||||
|
TRANSPORT_ID);
|
||||||
|
assertNotNull(ctx);
|
||||||
|
// Create a stream writer
|
||||||
|
StreamWriterFactory streamWriterFactory =
|
||||||
|
device.getStreamWriterFactory();
|
||||||
|
StreamWriter streamWriter =
|
||||||
|
streamWriterFactory.createStreamWriter(out, ctx);
|
||||||
|
// Create an outgoing sync session
|
||||||
|
SyncSessionFactory syncSessionFactory = device.getSyncSessionFactory();
|
||||||
|
SyncSession session = syncSessionFactory.createSimplexOutgoingSession(
|
||||||
|
contactId, MAX_LATENCY, streamWriter);
|
||||||
|
// Write whatever needs to be written
|
||||||
|
session.run();
|
||||||
|
streamWriter.sendEndOfStream();
|
||||||
|
// Return the contents of the stream
|
||||||
|
return out.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
private void createTestDataExceptions()
|
private void createTestDataExceptions()
|
||||||
throws DbException, FormatException {
|
throws DbException, FormatException {
|
||||||
String bobName =
|
String bobName =
|
||||||
|
|||||||
@@ -0,0 +1,161 @@
|
|||||||
|
package org.briarproject.briar.android;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.StrictMode;
|
||||||
|
|
||||||
|
import com.vanniktech.emoji.RecentEmoji;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||||
|
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||||
|
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||||
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.reporting.DevConfig;
|
||||||
|
import org.briarproject.bramble.util.AndroidUtils;
|
||||||
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
|
import org.briarproject.briar.android.account.LockManagerImpl;
|
||||||
|
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||||
|
import org.briarproject.briar.api.android.DozeWatchdog;
|
||||||
|
import org.briarproject.briar.api.android.LockManager;
|
||||||
|
import org.briarproject.briar.api.android.ScreenFilterMonitor;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import dagger.Module;
|
||||||
|
import dagger.Provides;
|
||||||
|
|
||||||
|
import static android.content.Context.MODE_PRIVATE;
|
||||||
|
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_ONION_ADDRESS;
|
||||||
|
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_PUBLIC_KEY_HEX;
|
||||||
|
|
||||||
|
@Module(includes = TestPluginConfigModule.class)
|
||||||
|
public class TestAppModule {
|
||||||
|
|
||||||
|
static class EagerSingletons {
|
||||||
|
@Inject
|
||||||
|
AndroidNotificationManager androidNotificationManager;
|
||||||
|
@Inject
|
||||||
|
NetworkUsageLogger networkUsageLogger;
|
||||||
|
@Inject
|
||||||
|
DozeWatchdog dozeWatchdog;
|
||||||
|
@Inject
|
||||||
|
RecentEmoji recentEmoji;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Application application;
|
||||||
|
|
||||||
|
public TestAppModule(Application application) {
|
||||||
|
this.application = application;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
Application providesApplication() {
|
||||||
|
return application;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
DatabaseConfig provideDatabaseConfig(Application app) {
|
||||||
|
//FIXME: StrictMode
|
||||||
|
StrictMode.ThreadPolicy tp = StrictMode.allowThreadDiskReads();
|
||||||
|
StrictMode.allowThreadDiskWrites();
|
||||||
|
File dbDir = app.getApplicationContext().getDir("db", MODE_PRIVATE);
|
||||||
|
File keyDir = app.getApplicationContext().getDir("key", MODE_PRIVATE);
|
||||||
|
StrictMode.setThreadPolicy(tp);
|
||||||
|
return new AndroidDatabaseConfig(dbDir, keyDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
DevConfig provideDevConfig(Application app, CryptoComponent crypto) {
|
||||||
|
@NotNullByDefault
|
||||||
|
DevConfig devConfig = new DevConfig() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PublicKey getDevPublicKey() {
|
||||||
|
try {
|
||||||
|
return crypto.getMessageKeyParser().parsePublicKey(
|
||||||
|
StringUtils.fromHexString(DEV_PUBLIC_KEY_HEX));
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDevOnionAddress() {
|
||||||
|
return DEV_ONION_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getReportDir() {
|
||||||
|
return AndroidUtils.getReportDir(app.getApplicationContext());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return devConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
SharedPreferences provideSharedPreferences(Application app) {
|
||||||
|
// FIXME unify this with getDefaultSharedPreferences()
|
||||||
|
return app.getSharedPreferences("db", MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
AndroidNotificationManager provideAndroidNotificationManager(
|
||||||
|
LifecycleManager lifecycleManager, EventBus eventBus,
|
||||||
|
AndroidNotificationManagerImpl notificationManager) {
|
||||||
|
lifecycleManager.registerService(notificationManager);
|
||||||
|
eventBus.addListener(notificationManager);
|
||||||
|
return notificationManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
ScreenFilterMonitor provideScreenFilterMonitor(
|
||||||
|
LifecycleManager lifecycleManager,
|
||||||
|
ScreenFilterMonitorImpl screenFilterMonitor) {
|
||||||
|
lifecycleManager.registerService(screenFilterMonitor);
|
||||||
|
return screenFilterMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
NetworkUsageLogger provideNetworkUsageLogger(
|
||||||
|
LifecycleManager lifecycleManager) {
|
||||||
|
NetworkUsageLogger networkUsageLogger = new NetworkUsageLogger();
|
||||||
|
lifecycleManager.registerService(networkUsageLogger);
|
||||||
|
return networkUsageLogger;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
DozeWatchdog provideDozeWatchdog(LifecycleManager lifecycleManager) {
|
||||||
|
DozeWatchdogImpl dozeWatchdog = new DozeWatchdogImpl(application);
|
||||||
|
lifecycleManager.registerService(dozeWatchdog);
|
||||||
|
return dozeWatchdog;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
LockManager provideLockManager(LifecycleManager lifecycleManager,
|
||||||
|
EventBus eventBus, LockManagerImpl lockManager) {
|
||||||
|
lifecycleManager.registerService(lockManager);
|
||||||
|
eventBus.addListener(lockManager);
|
||||||
|
return lockManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
RecentEmoji provideRecentEmoji(LifecycleManager lifecycleManager,
|
||||||
|
RecentEmojiImpl recentEmoji) {
|
||||||
|
lifecycleManager.registerClient(recentEmoji);
|
||||||
|
return recentEmoji;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package org.briarproject.briar.android;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.plugin.PluginConfig;
|
||||||
|
import org.briarproject.bramble.api.plugin.TransportId;
|
||||||
|
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
|
||||||
|
import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
|
||||||
|
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginCallback;
|
||||||
|
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import dagger.Module;
|
||||||
|
import dagger.Provides;
|
||||||
|
|
||||||
|
import static java.util.Collections.emptyList;
|
||||||
|
import static java.util.Collections.singletonList;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getTransportId;
|
||||||
|
|
||||||
|
@Module
|
||||||
|
public class TestPluginConfigModule {
|
||||||
|
|
||||||
|
public static final TransportId TRANSPORT_ID = getTransportId();
|
||||||
|
public static final int MAX_LATENCY = 2 * 60 * 1000; // 2 minutes
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
private final SimplexPluginFactory simplex = new SimplexPluginFactory() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TransportId getId() {
|
||||||
|
return TRANSPORT_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxLatency() {
|
||||||
|
return MAX_LATENCY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public SimplexPlugin createPlugin(SimplexPluginCallback callback) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
PluginConfig providePluginConfig() {
|
||||||
|
@NotNullByDefault
|
||||||
|
PluginConfig pluginConfig = new PluginConfig() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<DuplexPluginFactory> getDuplexFactories() {
|
||||||
|
return emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<SimplexPluginFactory> getSimplexFactories() {
|
||||||
|
return singletonList(simplex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldPoll() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return pluginConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -13,10 +13,9 @@
|
|||||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||||
<uses-permission android:name="android.permission.CAMERA" />
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
|
||||||
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
|
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||||
<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" />
|
||||||
|
|
||||||
@@ -26,7 +25,6 @@
|
|||||||
android:icon="@mipmap/ic_launcher_round"
|
android:icon="@mipmap/ic_launcher_round"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:logo="@mipmap/ic_launcher_round"
|
android:logo="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
|
||||||
android:theme="@style/BriarTheme">
|
android:theme="@style/BriarTheme">
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
@@ -387,7 +385,7 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name="org.briarproject.briar.android.panic.PanicResponderActivity"
|
android:name="org.briarproject.briar.android.panic.PanicResponderActivity"
|
||||||
android:noHistory="true"
|
android:noHistory="true"
|
||||||
android:theme="@style/Theme.AppCompat.NoActionBar">
|
android:theme="@android:style/Theme.NoDisplay">
|
||||||
<!-- this can never have launchMode singleTask or singleInstance! -->
|
<!-- this can never have launchMode singleTask or singleInstance! -->
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="info.guardianproject.panic.action.TRIGGER"/>
|
<action android:name="info.guardianproject.panic.action.TRIGGER"/>
|
||||||
@@ -397,12 +395,12 @@
|
|||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="org.briarproject.briar.android.logout.ExitActivity"
|
android:name="org.briarproject.briar.android.logout.ExitActivity"
|
||||||
android:theme="@style/Theme.AppCompat.NoActionBar">
|
android:theme="@android:style/Theme.NoDisplay">
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".android.logout.HideUiActivity"
|
android:name=".android.logout.HideUiActivity"
|
||||||
android:theme="@style/Theme.AppCompat.NoActionBar">
|
android:theme="@android:style/Theme.NoDisplay">
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
|
|||||||
@@ -41,9 +41,13 @@ import org.briarproject.briar.android.util.BriarNotificationBuilder;
|
|||||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||||
import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
|
import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
|
||||||
import org.briarproject.briar.api.forum.event.ForumPostReceivedEvent;
|
import org.briarproject.briar.api.forum.event.ForumPostReceivedEvent;
|
||||||
|
import org.briarproject.briar.api.introduction.event.IntroductionRequestReceivedEvent;
|
||||||
|
import org.briarproject.briar.api.introduction.event.IntroductionResponseReceivedEvent;
|
||||||
import org.briarproject.briar.api.introduction.event.IntroductionSucceededEvent;
|
import org.briarproject.briar.api.introduction.event.IntroductionSucceededEvent;
|
||||||
import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
|
import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
|
||||||
import org.briarproject.briar.api.privategroup.event.GroupMessageAddedEvent;
|
import org.briarproject.briar.api.privategroup.event.GroupMessageAddedEvent;
|
||||||
|
import org.briarproject.briar.api.sharing.event.InvitationRequestReceivedEvent;
|
||||||
|
import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
@@ -231,6 +235,19 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
} else if (e instanceof BlogPostAddedEvent) {
|
} else if (e instanceof BlogPostAddedEvent) {
|
||||||
BlogPostAddedEvent b = (BlogPostAddedEvent) e;
|
BlogPostAddedEvent b = (BlogPostAddedEvent) e;
|
||||||
showBlogPostNotification(b.getGroupId());
|
showBlogPostNotification(b.getGroupId());
|
||||||
|
} else if (e instanceof IntroductionRequestReceivedEvent) {
|
||||||
|
ContactId c = ((IntroductionRequestReceivedEvent) e).getContactId();
|
||||||
|
showContactNotification(c);
|
||||||
|
} else if (e instanceof IntroductionResponseReceivedEvent) {
|
||||||
|
ContactId c =
|
||||||
|
((IntroductionResponseReceivedEvent) e).getContactId();
|
||||||
|
showContactNotification(c);
|
||||||
|
} else if (e instanceof InvitationRequestReceivedEvent) {
|
||||||
|
ContactId c = ((InvitationRequestReceivedEvent) e).getContactId();
|
||||||
|
showContactNotification(c);
|
||||||
|
} else if (e instanceof InvitationResponseReceivedEvent) {
|
||||||
|
ContactId c = ((InvitationResponseReceivedEvent) e).getContactId();
|
||||||
|
showContactNotification(c);
|
||||||
} else if (e instanceof IntroductionSucceededEvent) {
|
} else if (e instanceof IntroductionSucceededEvent) {
|
||||||
showIntroductionNotification();
|
showIntroductionNotification();
|
||||||
}
|
}
|
||||||
@@ -310,7 +327,9 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
R.plurals.private_message_notification_text, contactTotal,
|
R.plurals.private_message_notification_text, contactTotal,
|
||||||
contactTotal));
|
contactTotal));
|
||||||
b.setNumber(contactTotal);
|
b.setNumber(contactTotal);
|
||||||
b.setNotificationCategory(CATEGORY_MESSAGE);
|
boolean showOnLockScreen =
|
||||||
|
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||||
|
b.setLockscreenVisibility(CATEGORY_MESSAGE, showOnLockScreen);
|
||||||
if (mayAlertAgain) setAlertProperties(b);
|
if (mayAlertAgain) setAlertProperties(b);
|
||||||
setDeleteIntent(b, CONTACT_URI);
|
setDeleteIntent(b, CONTACT_URI);
|
||||||
Set<ContactId> contacts = contactCounts.keySet();
|
Set<ContactId> contacts = contactCounts.keySet();
|
||||||
@@ -412,7 +431,9 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
R.plurals.group_message_notification_text, groupTotal,
|
R.plurals.group_message_notification_text, groupTotal,
|
||||||
groupTotal));
|
groupTotal));
|
||||||
b.setNumber(groupTotal);
|
b.setNumber(groupTotal);
|
||||||
b.setNotificationCategory(CATEGORY_SOCIAL);
|
boolean showOnLockScreen =
|
||||||
|
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||||
|
b.setLockscreenVisibility(CATEGORY_SOCIAL, showOnLockScreen);
|
||||||
if (mayAlertAgain) setAlertProperties(b);
|
if (mayAlertAgain) setAlertProperties(b);
|
||||||
setDeleteIntent(b, GROUP_URI);
|
setDeleteIntent(b, GROUP_URI);
|
||||||
Set<GroupId> groups = groupCounts.keySet();
|
Set<GroupId> groups = groupCounts.keySet();
|
||||||
@@ -483,7 +504,9 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
R.plurals.forum_post_notification_text, forumTotal,
|
R.plurals.forum_post_notification_text, forumTotal,
|
||||||
forumTotal));
|
forumTotal));
|
||||||
b.setNumber(forumTotal);
|
b.setNumber(forumTotal);
|
||||||
b.setNotificationCategory(CATEGORY_SOCIAL);
|
boolean showOnLockScreen =
|
||||||
|
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||||
|
b.setLockscreenVisibility(CATEGORY_SOCIAL, showOnLockScreen);
|
||||||
if (mayAlertAgain) setAlertProperties(b);
|
if (mayAlertAgain) setAlertProperties(b);
|
||||||
setDeleteIntent(b, FORUM_URI);
|
setDeleteIntent(b, FORUM_URI);
|
||||||
Set<GroupId> forums = forumCounts.keySet();
|
Set<GroupId> forums = forumCounts.keySet();
|
||||||
@@ -552,7 +575,9 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
R.plurals.blog_post_notification_text, blogTotal,
|
R.plurals.blog_post_notification_text, blogTotal,
|
||||||
blogTotal));
|
blogTotal));
|
||||||
b.setNumber(blogTotal);
|
b.setNumber(blogTotal);
|
||||||
b.setNotificationCategory(CATEGORY_SOCIAL);
|
boolean showOnLockScreen =
|
||||||
|
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||||
|
b.setLockscreenVisibility(CATEGORY_SOCIAL, showOnLockScreen);
|
||||||
if (mayAlertAgain) setAlertProperties(b);
|
if (mayAlertAgain) setAlertProperties(b);
|
||||||
setDeleteIntent(b, BLOG_URI);
|
setDeleteIntent(b, BLOG_URI);
|
||||||
// Touching the notification shows the combined blog feed
|
// Touching the notification shows the combined blog feed
|
||||||
@@ -593,7 +618,9 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
|||||||
b.setContentText(appContext.getResources().getQuantityString(
|
b.setContentText(appContext.getResources().getQuantityString(
|
||||||
R.plurals.introduction_notification_text, introductionTotal,
|
R.plurals.introduction_notification_text, introductionTotal,
|
||||||
introductionTotal));
|
introductionTotal));
|
||||||
b.setNotificationCategory(CATEGORY_MESSAGE);
|
boolean showOnLockScreen =
|
||||||
|
settings.getBoolean(PREF_NOTIFY_LOCK_SCREEN, false);
|
||||||
|
b.setLockscreenVisibility(CATEGORY_MESSAGE, showOnLockScreen);
|
||||||
setAlertProperties(b);
|
setAlertProperties(b);
|
||||||
setDeleteIntent(b, INTRODUCTION_URI);
|
setDeleteIntent(b, INTRODUCTION_URI);
|
||||||
// Touching the notification shows the contact list
|
// Touching the notification shows the contact list
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package org.briarproject.briar.android;
|
package org.briarproject.briar.android;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.StrictMode;
|
import android.os.StrictMode;
|
||||||
|
|
||||||
@@ -11,24 +10,9 @@ import org.briarproject.bramble.api.crypto.CryptoComponent;
|
|||||||
import org.briarproject.bramble.api.crypto.PublicKey;
|
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
|
||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
import org.briarproject.bramble.api.network.NetworkManager;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.plugin.BackoffFactory;
|
|
||||||
import org.briarproject.bramble.api.plugin.PluginConfig;
|
|
||||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
|
|
||||||
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
|
|
||||||
import org.briarproject.bramble.api.reporting.DevConfig;
|
import org.briarproject.bramble.api.reporting.DevConfig;
|
||||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
|
||||||
import org.briarproject.bramble.api.system.Clock;
|
|
||||||
import org.briarproject.bramble.api.system.LocationUtils;
|
|
||||||
import org.briarproject.bramble.api.system.ResourceProvider;
|
|
||||||
import org.briarproject.bramble.api.system.Scheduler;
|
|
||||||
import org.briarproject.bramble.plugin.bluetooth.AndroidBluetoothPluginFactory;
|
|
||||||
import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory;
|
|
||||||
import org.briarproject.bramble.plugin.tor.AndroidTorPluginFactory;
|
|
||||||
import org.briarproject.bramble.plugin.tor.CircumventionProvider;
|
|
||||||
import org.briarproject.bramble.util.AndroidUtils;
|
import org.briarproject.bramble.util.AndroidUtils;
|
||||||
import org.briarproject.bramble.util.StringUtils;
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
import org.briarproject.briar.android.account.LockManagerImpl;
|
import org.briarproject.briar.android.account.LockManagerImpl;
|
||||||
@@ -39,25 +23,18 @@ import org.briarproject.briar.api.android.ScreenFilterMonitor;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.net.SocketFactory;
|
|
||||||
|
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
|
|
||||||
import static android.content.Context.MODE_PRIVATE;
|
import static android.content.Context.MODE_PRIVATE;
|
||||||
import static java.util.Arrays.asList;
|
|
||||||
import static java.util.Collections.emptyList;
|
|
||||||
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_ONION_ADDRESS;
|
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_ONION_ADDRESS;
|
||||||
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_PUBLIC_KEY_HEX;
|
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_PUBLIC_KEY_HEX;
|
||||||
|
|
||||||
@Module
|
@Module(includes = PluginConfigModule.class)
|
||||||
public class AppModule {
|
public class AppModule {
|
||||||
|
|
||||||
static class EagerSingletons {
|
static class EagerSingletons {
|
||||||
@@ -95,47 +72,6 @@ public class AppModule {
|
|||||||
return new AndroidDatabaseConfig(dbDir, keyDir);
|
return new AndroidDatabaseConfig(dbDir, keyDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
|
||||||
PluginConfig providePluginConfig(@IoExecutor Executor ioExecutor,
|
|
||||||
@Scheduler ScheduledExecutorService scheduler,
|
|
||||||
AndroidExecutor androidExecutor, SecureRandom random,
|
|
||||||
SocketFactory torSocketFactory, BackoffFactory backoffFactory,
|
|
||||||
Application app, NetworkManager networkManager,
|
|
||||||
LocationUtils locationUtils, EventBus eventBus,
|
|
||||||
ResourceProvider resourceProvider,
|
|
||||||
CircumventionProvider circumventionProvider, Clock clock) {
|
|
||||||
Context appContext = app.getApplicationContext();
|
|
||||||
DuplexPluginFactory bluetooth =
|
|
||||||
new AndroidBluetoothPluginFactory(ioExecutor, androidExecutor,
|
|
||||||
appContext, random, eventBus, backoffFactory);
|
|
||||||
DuplexPluginFactory tor = new AndroidTorPluginFactory(ioExecutor,
|
|
||||||
scheduler, appContext, networkManager, locationUtils, eventBus,
|
|
||||||
torSocketFactory, backoffFactory, resourceProvider,
|
|
||||||
circumventionProvider, clock);
|
|
||||||
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
|
|
||||||
eventBus, backoffFactory, appContext);
|
|
||||||
Collection<DuplexPluginFactory> duplex = asList(bluetooth, tor, lan);
|
|
||||||
@NotNullByDefault
|
|
||||||
PluginConfig pluginConfig = new PluginConfig() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<DuplexPluginFactory> getDuplexFactories() {
|
|
||||||
return duplex;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<SimplexPluginFactory> getSimplexFactories() {
|
|
||||||
return emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldPoll() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return pluginConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
DevConfig provideDevConfig(Application app, CryptoComponent crypto) {
|
DevConfig provideDevConfig(Application app, CryptoComponent crypto) {
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package org.briarproject.briar.android;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
|
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||||
|
import org.briarproject.bramble.api.network.NetworkManager;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.plugin.BackoffFactory;
|
||||||
|
import org.briarproject.bramble.api.plugin.PluginConfig;
|
||||||
|
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
|
||||||
|
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
|
||||||
|
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||||
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
|
import org.briarproject.bramble.api.system.LocationUtils;
|
||||||
|
import org.briarproject.bramble.api.system.ResourceProvider;
|
||||||
|
import org.briarproject.bramble.api.system.Scheduler;
|
||||||
|
import org.briarproject.bramble.plugin.bluetooth.AndroidBluetoothPluginFactory;
|
||||||
|
import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory;
|
||||||
|
import org.briarproject.bramble.plugin.tor.AndroidTorPluginFactory;
|
||||||
|
import org.briarproject.bramble.plugin.tor.CircumventionProvider;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
|
||||||
|
import javax.net.SocketFactory;
|
||||||
|
|
||||||
|
import dagger.Module;
|
||||||
|
import dagger.Provides;
|
||||||
|
|
||||||
|
import static java.util.Arrays.asList;
|
||||||
|
import static java.util.Collections.emptyList;
|
||||||
|
|
||||||
|
@Module
|
||||||
|
public class PluginConfigModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
PluginConfig providePluginConfig(@IoExecutor Executor ioExecutor,
|
||||||
|
@Scheduler ScheduledExecutorService scheduler,
|
||||||
|
AndroidExecutor androidExecutor, SecureRandom random,
|
||||||
|
SocketFactory torSocketFactory, BackoffFactory backoffFactory,
|
||||||
|
Application app, NetworkManager networkManager,
|
||||||
|
LocationUtils locationUtils, EventBus eventBus,
|
||||||
|
ResourceProvider resourceProvider,
|
||||||
|
CircumventionProvider circumventionProvider, Clock clock) {
|
||||||
|
Context appContext = app.getApplicationContext();
|
||||||
|
DuplexPluginFactory bluetooth =
|
||||||
|
new AndroidBluetoothPluginFactory(ioExecutor, androidExecutor,
|
||||||
|
appContext, random, eventBus, backoffFactory);
|
||||||
|
DuplexPluginFactory tor = new AndroidTorPluginFactory(ioExecutor,
|
||||||
|
scheduler, appContext, networkManager, locationUtils, eventBus,
|
||||||
|
torSocketFactory, backoffFactory, resourceProvider,
|
||||||
|
circumventionProvider, clock);
|
||||||
|
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
|
||||||
|
eventBus, backoffFactory, appContext);
|
||||||
|
Collection<DuplexPluginFactory> duplex = asList(bluetooth, tor, lan);
|
||||||
|
@NotNullByDefault
|
||||||
|
PluginConfig pluginConfig = new PluginConfig() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<DuplexPluginFactory> getDuplexFactories() {
|
||||||
|
return duplex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<SimplexPluginFactory> getSimplexFactories() {
|
||||||
|
return emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldPoll() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return pluginConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -101,8 +101,6 @@ public class LockManagerImpl implements LockManager, Service, EventListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stopService() {
|
public void stopService() {
|
||||||
timeoutMinutes = timeoutNever;
|
|
||||||
if (alarmSet) alarmManager.cancel(lockIntent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import org.briarproject.briar.android.controller.ActivityLifecycleController;
|
|||||||
import org.briarproject.briar.android.forum.ForumModule;
|
import org.briarproject.briar.android.forum.ForumModule;
|
||||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||||
import org.briarproject.briar.android.fragment.ScreenFilterDialogFragment;
|
import org.briarproject.briar.android.fragment.ScreenFilterDialogFragment;
|
||||||
import org.briarproject.briar.android.reporting.DevReportActivity;
|
|
||||||
import org.briarproject.briar.android.util.UiUtils;
|
import org.briarproject.briar.android.util.UiUtils;
|
||||||
import org.briarproject.briar.android.widget.TapSafeFrameLayout;
|
import org.briarproject.briar.android.widget.TapSafeFrameLayout;
|
||||||
import org.briarproject.briar.android.widget.TapSafeFrameLayout.OnTapFilteredListener;
|
import org.briarproject.briar.android.widget.TapSafeFrameLayout.OnTapFilteredListener;
|
||||||
@@ -38,16 +37,11 @@ import java.util.List;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static android.arch.lifecycle.Lifecycle.State.STARTED;
|
|
||||||
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
||||||
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
|
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
|
||||||
import static android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT;
|
import static android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT;
|
||||||
import static org.briarproject.briar.android.TestingConstants.PREVENT_SCREENSHOTS;
|
import static org.briarproject.briar.android.TestingConstants.PREVENT_SCREENSHOTS;
|
||||||
|
|
||||||
/**
|
|
||||||
* Warning: Some activities don't extend {@link BaseActivity}.
|
|
||||||
* E.g. {@link DevReportActivity}
|
|
||||||
*/
|
|
||||||
public abstract class BaseActivity extends AppCompatActivity
|
public abstract class BaseActivity extends AppCompatActivity
|
||||||
implements DestroyableContext, OnTapFilteredListener {
|
implements DestroyableContext, OnTapFilteredListener {
|
||||||
|
|
||||||
@@ -149,7 +143,6 @@ public abstract class BaseActivity extends AppCompatActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void showNextFragment(BaseFragment f) {
|
public void showNextFragment(BaseFragment f) {
|
||||||
if (!getLifecycle().getCurrentState().isAtLeast(STARTED)) return;
|
|
||||||
getSupportFragmentManager().beginTransaction()
|
getSupportFragmentManager().beginTransaction()
|
||||||
.setCustomAnimations(R.anim.step_next_in,
|
.setCustomAnimations(R.anim.step_next_in,
|
||||||
R.anim.step_previous_out, R.anim.step_previous_in,
|
R.anim.step_previous_out, R.anim.step_previous_in,
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ abstract class BaseControllerImpl extends DbControllerImpl
|
|||||||
protected final IdentityManager identityManager;
|
protected final IdentityManager identityManager;
|
||||||
protected final BlogManager blogManager;
|
protected final BlogManager blogManager;
|
||||||
|
|
||||||
private final Map<MessageId, String> textCache = new ConcurrentHashMap<>();
|
private final Map<MessageId, String> bodyCache = new ConcurrentHashMap<>();
|
||||||
private final Map<MessageId, BlogPostHeader> headerCache =
|
private final Map<MessageId, BlogPostHeader> headerCache =
|
||||||
new ConcurrentHashMap<>();
|
new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@@ -129,17 +129,17 @@ abstract class BaseControllerImpl extends DbControllerImpl
|
|||||||
public void loadBlogPost(BlogPostHeader header,
|
public void loadBlogPost(BlogPostHeader header,
|
||||||
ResultExceptionHandler<BlogPostItem, DbException> handler) {
|
ResultExceptionHandler<BlogPostItem, DbException> handler) {
|
||||||
|
|
||||||
String text = textCache.get(header.getId());
|
String body = bodyCache.get(header.getId());
|
||||||
if (text != null) {
|
if (body != null) {
|
||||||
LOG.info("Loaded text from cache");
|
LOG.info("Loaded body from cache");
|
||||||
handler.onResult(new BlogPostItem(header, text));
|
handler.onResult(new BlogPostItem(header, body));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
long start = now();
|
long start = now();
|
||||||
BlogPostItem item = getItem(header);
|
BlogPostItem item = getItem(header);
|
||||||
logDuration(LOG, "Loading text", start);
|
logDuration(LOG, "Loading body", start);
|
||||||
handler.onResult(item);
|
handler.onResult(item);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
@@ -200,28 +200,28 @@ abstract class BaseControllerImpl extends DbControllerImpl
|
|||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private BlogPostItem getItem(BlogPostHeader h) throws DbException {
|
private BlogPostItem getItem(BlogPostHeader h) throws DbException {
|
||||||
String text;
|
String body;
|
||||||
if (h instanceof BlogCommentHeader) {
|
if (h instanceof BlogCommentHeader) {
|
||||||
BlogCommentHeader c = (BlogCommentHeader) h;
|
BlogCommentHeader c = (BlogCommentHeader) h;
|
||||||
BlogCommentItem item = new BlogCommentItem(c);
|
BlogCommentItem item = new BlogCommentItem(c);
|
||||||
text = getPostText(item.getPostHeader().getId());
|
body = getPostBody(item.getPostHeader().getId());
|
||||||
item.setText(text);
|
item.setBody(body);
|
||||||
return item;
|
return item;
|
||||||
} else {
|
} else {
|
||||||
text = getPostText(h.getId());
|
body = getPostBody(h.getId());
|
||||||
return new BlogPostItem(h, text);
|
return new BlogPostItem(h, body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private String getPostText(MessageId m) throws DbException {
|
private String getPostBody(MessageId m) throws DbException {
|
||||||
String text = textCache.get(m);
|
String body = bodyCache.get(m);
|
||||||
if (text == null) {
|
if (body == null) {
|
||||||
text = HtmlUtils.clean(blogManager.getPostText(m), ARTICLE);
|
body = HtmlUtils.clean(blogManager.getPostBody(m), ARTICLE);
|
||||||
textCache.put(m, text);
|
bodyCache.put(m, body);
|
||||||
}
|
}
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
return text;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ class BlogCommentItem extends BlogPostItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setText(String text) {
|
public void setBody(String body) {
|
||||||
this.text = text;
|
this.body = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ import org.briarproject.briar.android.controller.ActivityLifecycleController;
|
|||||||
import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
|
import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
|
||||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||||
import org.briarproject.briar.api.blog.Blog;
|
import org.briarproject.briar.api.blog.Blog;
|
||||||
import org.briarproject.briar.api.blog.BlogInvitationResponse;
|
|
||||||
import org.briarproject.briar.api.blog.BlogManager;
|
import org.briarproject.briar.api.blog.BlogManager;
|
||||||
import org.briarproject.briar.api.blog.BlogSharingManager;
|
import org.briarproject.briar.api.blog.BlogSharingManager;
|
||||||
import org.briarproject.briar.api.blog.event.BlogInvitationResponseReceivedEvent;
|
import org.briarproject.briar.api.blog.event.BlogInvitationResponseReceivedEvent;
|
||||||
import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
|
import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
|
||||||
|
import org.briarproject.briar.api.sharing.InvitationResponse;
|
||||||
import org.briarproject.briar.api.sharing.event.ContactLeftShareableEvent;
|
import org.briarproject.briar.api.sharing.event.ContactLeftShareableEvent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -107,7 +107,7 @@ class BlogControllerImpl extends BaseControllerImpl
|
|||||||
} else if (e instanceof BlogInvitationResponseReceivedEvent) {
|
} else if (e instanceof BlogInvitationResponseReceivedEvent) {
|
||||||
BlogInvitationResponseReceivedEvent b =
|
BlogInvitationResponseReceivedEvent b =
|
||||||
(BlogInvitationResponseReceivedEvent) e;
|
(BlogInvitationResponseReceivedEvent) e;
|
||||||
BlogInvitationResponse r = b.getMessageHeader();
|
InvitationResponse r = b.getResponse();
|
||||||
if (r.getShareableId().equals(groupId) && r.wasAccepted()) {
|
if (r.getShareableId().equals(groupId) && r.wasAccepted()) {
|
||||||
LOG.info("Blog invitation accepted");
|
LOG.info("Blog invitation accepted");
|
||||||
onBlogInvitationAccepted(b.getContactId());
|
onBlogInvitationAccepted(b.getContactId());
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ import javax.annotation.concurrent.NotThreadSafe;
|
|||||||
public class BlogPostItem implements Comparable<BlogPostItem> {
|
public class BlogPostItem implements Comparable<BlogPostItem> {
|
||||||
|
|
||||||
private final BlogPostHeader header;
|
private final BlogPostHeader header;
|
||||||
protected String text;
|
protected String body;
|
||||||
private boolean read;
|
private boolean read;
|
||||||
|
|
||||||
BlogPostItem(BlogPostHeader header, @Nullable String text) {
|
BlogPostItem(BlogPostHeader header, @Nullable String body) {
|
||||||
this.header = header;
|
this.header = header;
|
||||||
this.text = text;
|
this.body = body;
|
||||||
this.read = header.isRead();
|
this.read = header.isRead();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,8 +44,8 @@ public class BlogPostItem implements Comparable<BlogPostItem> {
|
|||||||
return header.getAuthorStatus();
|
return header.getAuthorStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getText() {
|
public String getBody() {
|
||||||
return text;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRssFeed() {
|
public boolean isRssFeed() {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
|||||||
private final AuthorView reblogger;
|
private final AuthorView reblogger;
|
||||||
private final AuthorView author;
|
private final AuthorView author;
|
||||||
private final ImageButton reblogButton;
|
private final ImageButton reblogButton;
|
||||||
private final TextView text;
|
private final TextView body;
|
||||||
private final ViewGroup commentContainer;
|
private final ViewGroup commentContainer;
|
||||||
private final boolean fullText;
|
private final boolean fullText;
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
|||||||
reblogger = v.findViewById(R.id.rebloggerView);
|
reblogger = v.findViewById(R.id.rebloggerView);
|
||||||
author = v.findViewById(R.id.authorView);
|
author = v.findViewById(R.id.authorView);
|
||||||
reblogButton = v.findViewById(R.id.commentView);
|
reblogButton = v.findViewById(R.id.commentView);
|
||||||
text = v.findViewById(R.id.textView);
|
body = v.findViewById(R.id.bodyView);
|
||||||
commentContainer = v.findViewById(R.id.commentContainer);
|
commentContainer = v.findViewById(R.id.commentContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,17 +111,17 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
|||||||
author.setAuthorNotClickable();
|
author.setAuthorNotClickable();
|
||||||
}
|
}
|
||||||
|
|
||||||
// post text
|
// post body
|
||||||
Spanned postText = getSpanned(item.getText());
|
Spanned bodyText = getSpanned(item.getBody());
|
||||||
if (fullText) {
|
if (fullText) {
|
||||||
text.setText(postText);
|
body.setText(bodyText);
|
||||||
text.setTextIsSelectable(true);
|
body.setTextIsSelectable(true);
|
||||||
makeLinksClickable(text, fragmentManager);
|
makeLinksClickable(body, fragmentManager);
|
||||||
} else {
|
} else {
|
||||||
text.setTextIsSelectable(false);
|
body.setTextIsSelectable(false);
|
||||||
if (postText.length() > TEASER_LENGTH)
|
if (bodyText.length() > TEASER_LENGTH)
|
||||||
postText = getTeaser(ctx, postText);
|
bodyText = getTeaser(ctx, bodyText);
|
||||||
text.setText(postText);
|
body.setText(bodyText);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reblog button
|
// reblog button
|
||||||
@@ -163,15 +163,15 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
|||||||
commentContainer, false);
|
commentContainer, false);
|
||||||
|
|
||||||
AuthorView author = v.findViewById(R.id.authorView);
|
AuthorView author = v.findViewById(R.id.authorView);
|
||||||
TextView text = v.findViewById(R.id.textView);
|
TextView body = v.findViewById(R.id.bodyView);
|
||||||
|
|
||||||
author.setAuthor(c.getAuthor());
|
author.setAuthor(c.getAuthor());
|
||||||
author.setAuthorStatus(c.getAuthorStatus());
|
author.setAuthorStatus(c.getAuthorStatus());
|
||||||
author.setDate(c.getTimestamp());
|
author.setDate(c.getTimestamp());
|
||||||
// TODO make author clickable #624
|
// TODO make author clickable #624
|
||||||
|
|
||||||
text.setText(c.getComment());
|
body.setText(c.getComment());
|
||||||
if (fullText) text.setTextIsSelectable(true);
|
if (fullText) body.setTextIsSelectable(true);
|
||||||
|
|
||||||
commentContainer.addView(v);
|
commentContainer.addView(v);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import static android.view.View.GONE;
|
|||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.briar.api.blog.BlogConstants.MAX_BLOG_POST_TEXT_LENGTH;
|
import static org.briarproject.briar.api.blog.BlogConstants.MAX_BLOG_POST_BODY_LENGTH;
|
||||||
|
|
||||||
public class WriteBlogPostActivity extends BriarActivity
|
public class WriteBlogPostActivity extends BriarActivity
|
||||||
implements OnEditorActionListener, TextInputListener {
|
implements OnEditorActionListener, TextInputListener {
|
||||||
@@ -70,7 +70,7 @@ public class WriteBlogPostActivity extends BriarActivity
|
|||||||
|
|
||||||
setContentView(R.layout.activity_write_blog_post);
|
setContentView(R.layout.activity_write_blog_post);
|
||||||
|
|
||||||
input = findViewById(R.id.textInput);
|
input = findViewById(R.id.bodyInput);
|
||||||
input.setSendButtonEnabled(false);
|
input.setSendButtonEnabled(false);
|
||||||
input.addTextChangedListener(new TextWatcher() {
|
input.addTextChangedListener(new TextWatcher() {
|
||||||
@Override
|
@Override
|
||||||
@@ -132,23 +132,23 @@ public class WriteBlogPostActivity extends BriarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSendClick(String text) {
|
public void onSendClick(String body) {
|
||||||
// hide publish button, show progress bar
|
// hide publish button, show progress bar
|
||||||
input.hideSoftKeyboard();
|
input.hideSoftKeyboard();
|
||||||
input.setVisibility(GONE);
|
input.setVisibility(GONE);
|
||||||
progressBar.setVisibility(VISIBLE);
|
progressBar.setVisibility(VISIBLE);
|
||||||
|
|
||||||
text = StringUtils.truncateUtf8(text, MAX_BLOG_POST_TEXT_LENGTH);
|
body = StringUtils.truncateUtf8(body, MAX_BLOG_POST_BODY_LENGTH);
|
||||||
storePost(text);
|
storePost(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void storePost(String text) {
|
private void storePost(String body) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
long timestamp = System.currentTimeMillis();
|
long timestamp = System.currentTimeMillis();
|
||||||
try {
|
try {
|
||||||
LocalAuthor author = identityManager.getLocalAuthor();
|
LocalAuthor author = identityManager.getLocalAuthor();
|
||||||
BlogPost p = blogPostFactory
|
BlogPost p = blogPostFactory
|
||||||
.createBlogPost(groupId, timestamp, null, author, text);
|
.createBlogPost(groupId, timestamp, null, author, body);
|
||||||
blogManager.addLocalPost(p);
|
blogManager.addLocalPost(p);
|
||||||
postPublished();
|
postPublished();
|
||||||
} catch (DbException | GeneralSecurityException
|
} catch (DbException | GeneralSecurityException
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.briarproject.briar.android.contact;
|
package org.briarproject.briar.android.contact;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.ActivityCompat;
|
import android.support.v4.app.ActivityCompat;
|
||||||
import android.support.v4.app.ActivityOptionsCompat;
|
import android.support.v4.app.ActivityOptionsCompat;
|
||||||
@@ -35,10 +36,19 @@ import org.briarproject.briar.android.fragment.BaseFragment;
|
|||||||
import org.briarproject.briar.android.keyagreement.ContactExchangeActivity;
|
import org.briarproject.briar.android.keyagreement.ContactExchangeActivity;
|
||||||
import org.briarproject.briar.android.view.BriarRecyclerView;
|
import org.briarproject.briar.android.view.BriarRecyclerView;
|
||||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||||
|
import org.briarproject.briar.api.client.BaseMessageHeader;
|
||||||
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
|
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
|
||||||
|
import org.briarproject.briar.api.introduction.IntroductionRequest;
|
||||||
|
import org.briarproject.briar.api.introduction.IntroductionResponse;
|
||||||
|
import org.briarproject.briar.api.introduction.event.IntroductionRequestReceivedEvent;
|
||||||
|
import org.briarproject.briar.api.introduction.event.IntroductionResponseReceivedEvent;
|
||||||
import org.briarproject.briar.api.messaging.ConversationManager;
|
import org.briarproject.briar.api.messaging.ConversationManager;
|
||||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
|
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
|
||||||
import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
|
import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
|
||||||
|
import org.briarproject.briar.api.sharing.InvitationRequest;
|
||||||
|
import org.briarproject.briar.api.sharing.InvitationResponse;
|
||||||
|
import org.briarproject.briar.api.sharing.event.InvitationRequestReceivedEvent;
|
||||||
|
import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -47,7 +57,6 @@ import java.util.logging.Logger;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static android.support.v4.app.ActivityOptionsCompat.makeSceneTransitionAnimation;
|
import static android.support.v4.app.ActivityOptionsCompat.makeSceneTransitionAnimation;
|
||||||
import static android.support.v4.view.ViewCompat.getTransitionName;
|
import static android.support.v4.view.ViewCompat.getTransitionName;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
@@ -113,7 +122,7 @@ public class ContactListFragment extends BaseFragment implements EventListener {
|
|||||||
ContactId contactId = item.getContact().getId();
|
ContactId contactId = item.getContact().getId();
|
||||||
i.putExtra(CONTACT_ID, contactId.getInt());
|
i.putExtra(CONTACT_ID, contactId.getInt());
|
||||||
|
|
||||||
if (SDK_INT >= 23) {
|
if (Build.VERSION.SDK_INT >= 23) {
|
||||||
ContactListItemViewHolder holder =
|
ContactListItemViewHolder holder =
|
||||||
(ContactListItemViewHolder) list
|
(ContactListItemViewHolder) list
|
||||||
.getRecyclerView()
|
.getRecyclerView()
|
||||||
@@ -247,16 +256,41 @@ public class ContactListFragment extends BaseFragment implements EventListener {
|
|||||||
PrivateMessageReceivedEvent p = (PrivateMessageReceivedEvent) e;
|
PrivateMessageReceivedEvent p = (PrivateMessageReceivedEvent) e;
|
||||||
PrivateMessageHeader h = p.getMessageHeader();
|
PrivateMessageHeader h = p.getMessageHeader();
|
||||||
updateItem(p.getContactId(), h);
|
updateItem(p.getContactId(), h);
|
||||||
|
} else if (e instanceof IntroductionRequestReceivedEvent) {
|
||||||
|
LOG.info("Introduction request received, updating item");
|
||||||
|
IntroductionRequestReceivedEvent m =
|
||||||
|
(IntroductionRequestReceivedEvent) e;
|
||||||
|
IntroductionRequest ir = m.getIntroductionRequest();
|
||||||
|
updateItem(m.getContactId(), ir);
|
||||||
|
} else if (e instanceof IntroductionResponseReceivedEvent) {
|
||||||
|
LOG.info("Introduction response received, updating item");
|
||||||
|
IntroductionResponseReceivedEvent m =
|
||||||
|
(IntroductionResponseReceivedEvent) e;
|
||||||
|
IntroductionResponse ir = m.getIntroductionResponse();
|
||||||
|
updateItem(m.getContactId(), ir);
|
||||||
|
} else if (e instanceof InvitationRequestReceivedEvent) {
|
||||||
|
LOG.info("Invitation Request received, update item");
|
||||||
|
InvitationRequestReceivedEvent m =
|
||||||
|
(InvitationRequestReceivedEvent) e;
|
||||||
|
InvitationRequest ir = m.getRequest();
|
||||||
|
updateItem(m.getContactId(), ir);
|
||||||
|
} else if (e instanceof InvitationResponseReceivedEvent) {
|
||||||
|
LOG.info("Invitation response received, updating item");
|
||||||
|
InvitationResponseReceivedEvent m =
|
||||||
|
(InvitationResponseReceivedEvent) e;
|
||||||
|
InvitationResponse ir = m.getResponse();
|
||||||
|
updateItem(m.getContactId(), ir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateItem(ContactId c, PrivateMessageHeader h) {
|
private void updateItem(ContactId c, BaseMessageHeader h) {
|
||||||
runOnUiThreadUnlessDestroyed(() -> {
|
runOnUiThreadUnlessDestroyed(() -> {
|
||||||
adapter.incrementRevision();
|
adapter.incrementRevision();
|
||||||
int position = adapter.findItemPosition(c);
|
int position = adapter.findItemPosition(c);
|
||||||
ContactListItem item = adapter.getItemAt(position);
|
ContactListItem item = adapter.getItemAt(position);
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
item.addMessage(h);
|
ConversationItem i = ConversationItem.from(getContext(), h);
|
||||||
|
item.addMessage(i);
|
||||||
adapter.updateItemAt(position, item);
|
adapter.updateItemAt(position, item);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package org.briarproject.briar.android.contact;
|
|||||||
import org.briarproject.bramble.api.contact.Contact;
|
import org.briarproject.bramble.api.contact.Contact;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
|
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
|
||||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
|
|
||||||
|
|
||||||
import javax.annotation.concurrent.NotThreadSafe;
|
import javax.annotation.concurrent.NotThreadSafe;
|
||||||
|
|
||||||
@@ -23,10 +22,11 @@ public class ContactListItem extends ContactItem {
|
|||||||
this.timestamp = count.getLatestMsgTime();
|
this.timestamp = count.getLatestMsgTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
void addMessage(PrivateMessageHeader h) {
|
void addMessage(ConversationItem message) {
|
||||||
empty = false;
|
empty = false;
|
||||||
if (h.getTimestamp() > timestamp) timestamp = h.getTimestamp();
|
if (message.getTime() > timestamp) timestamp = message.getTime();
|
||||||
if (!h.isRead()) unread++;
|
if (!message.isRead())
|
||||||
|
unread++;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isEmpty() {
|
boolean isEmpty() {
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ import org.briarproject.briar.R;
|
|||||||
import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener;
|
import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener;
|
||||||
import org.briarproject.briar.android.util.UiUtils;
|
import org.briarproject.briar.android.util.UiUtils;
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import static android.support.v4.view.ViewCompat.setTransitionName;
|
import static android.support.v4.view.ViewCompat.setTransitionName;
|
||||||
@@ -38,7 +36,7 @@ class ContactListItemViewHolder extends ContactItemViewHolder<ContactListItem> {
|
|||||||
// unread count
|
// unread count
|
||||||
int unreadCount = item.getUnreadCount();
|
int unreadCount = item.getUnreadCount();
|
||||||
if (unreadCount > 0) {
|
if (unreadCount > 0) {
|
||||||
unread.setText(String.format(Locale.getDefault(), "%d", unreadCount));
|
unread.setText(String.valueOf(unreadCount));
|
||||||
unread.setVisibility(View.VISIBLE);
|
unread.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
unread.setVisibility(View.INVISIBLE);
|
unread.setVisibility(View.INVISIBLE);
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
package org.briarproject.briar.android.contact;
|
package org.briarproject.briar.android.contact;
|
||||||
|
|
||||||
import android.arch.lifecycle.MutableLiveData;
|
|
||||||
import android.arch.lifecycle.Observer;
|
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.annotation.UiThread;
|
import android.support.annotation.UiThread;
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
@@ -53,7 +50,6 @@ import org.briarproject.briar.android.activity.ActivityComponent;
|
|||||||
import org.briarproject.briar.android.activity.BriarActivity;
|
import org.briarproject.briar.android.activity.BriarActivity;
|
||||||
import org.briarproject.briar.android.blog.BlogActivity;
|
import org.briarproject.briar.android.blog.BlogActivity;
|
||||||
import org.briarproject.briar.android.contact.ConversationAdapter.ConversationListener;
|
import org.briarproject.briar.android.contact.ConversationAdapter.ConversationListener;
|
||||||
import org.briarproject.briar.android.contact.ConversationVisitor.TextCache;
|
|
||||||
import org.briarproject.briar.android.forum.ForumActivity;
|
import org.briarproject.briar.android.forum.ForumActivity;
|
||||||
import org.briarproject.briar.android.introduction.IntroductionActivity;
|
import org.briarproject.briar.android.introduction.IntroductionActivity;
|
||||||
import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
|
import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
|
||||||
@@ -66,15 +62,24 @@ import org.briarproject.briar.api.client.ProtocolStateException;
|
|||||||
import org.briarproject.briar.api.client.SessionId;
|
import org.briarproject.briar.api.client.SessionId;
|
||||||
import org.briarproject.briar.api.forum.ForumSharingManager;
|
import org.briarproject.briar.api.forum.ForumSharingManager;
|
||||||
import org.briarproject.briar.api.introduction.IntroductionManager;
|
import org.briarproject.briar.api.introduction.IntroductionManager;
|
||||||
import org.briarproject.briar.api.messaging.ConversationManager;
|
import org.briarproject.briar.api.introduction.IntroductionMessage;
|
||||||
|
import org.briarproject.briar.api.introduction.IntroductionRequest;
|
||||||
|
import org.briarproject.briar.api.introduction.IntroductionResponse;
|
||||||
|
import org.briarproject.briar.api.introduction.event.IntroductionRequestReceivedEvent;
|
||||||
|
import org.briarproject.briar.api.introduction.event.IntroductionResponseReceivedEvent;
|
||||||
import org.briarproject.briar.api.messaging.MessagingManager;
|
import org.briarproject.briar.api.messaging.MessagingManager;
|
||||||
import org.briarproject.briar.api.messaging.PrivateMessage;
|
import org.briarproject.briar.api.messaging.PrivateMessage;
|
||||||
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
|
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
|
||||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
|
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
|
||||||
import org.briarproject.briar.api.messaging.PrivateRequest;
|
|
||||||
import org.briarproject.briar.api.messaging.PrivateResponse;
|
|
||||||
import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
|
import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
|
||||||
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
|
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
|
||||||
|
import org.briarproject.briar.api.sharing.InvitationMessage;
|
||||||
|
import org.briarproject.briar.api.sharing.InvitationRequest;
|
||||||
|
import org.briarproject.briar.api.sharing.InvitationResponse;
|
||||||
|
import org.briarproject.briar.api.sharing.event.InvitationRequestReceivedEvent;
|
||||||
|
import org.briarproject.briar.api.sharing.event.InvitationResponseReceivedEvent;
|
||||||
|
import org.thoughtcrime.securesms.components.util.FutureTaskListener;
|
||||||
|
import org.thoughtcrime.securesms.components.util.ListenableFutureTask;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -82,10 +87,13 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import de.hdodenhof.circleimageview.CircleImageView;
|
import de.hdodenhof.circleimageview.CircleImageView;
|
||||||
@@ -105,15 +113,14 @@ import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_INTRO
|
|||||||
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
|
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
|
||||||
import static org.briarproject.briar.android.util.UiUtils.getAvatarTransitionName;
|
import static org.briarproject.briar.android.util.UiUtils.getAvatarTransitionName;
|
||||||
import static org.briarproject.briar.android.util.UiUtils.getBulbTransitionName;
|
import static org.briarproject.briar.android.util.UiUtils.getBulbTransitionName;
|
||||||
import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_TEXT_LENGTH;
|
import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
|
||||||
import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.STATE_DISMISSED;
|
import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.STATE_DISMISSED;
|
||||||
import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.STATE_FINISHED;
|
import static uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt.STATE_FINISHED;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public class ConversationActivity extends BriarActivity
|
public class ConversationActivity extends BriarActivity
|
||||||
implements EventListener, ConversationListener, TextInputListener,
|
implements EventListener, ConversationListener, TextInputListener {
|
||||||
TextCache {
|
|
||||||
|
|
||||||
public static final String CONTACT_ID = "briar.CONTACT_ID";
|
public static final String CONTACT_ID = "briar.CONTACT_ID";
|
||||||
|
|
||||||
@@ -130,10 +137,8 @@ public class ConversationActivity extends BriarActivity
|
|||||||
@CryptoExecutor
|
@CryptoExecutor
|
||||||
Executor cryptoExecutor;
|
Executor cryptoExecutor;
|
||||||
|
|
||||||
private final Map<MessageId, String> textCache = new ConcurrentHashMap<>();
|
private final Map<MessageId, String> bodyCache = new ConcurrentHashMap<>();
|
||||||
private final MutableLiveData<String> contactName = new MutableLiveData<>();
|
|
||||||
|
|
||||||
private ConversationVisitor visitor;
|
|
||||||
private ConversationAdapter adapter;
|
private ConversationAdapter adapter;
|
||||||
private Toolbar toolbar;
|
private Toolbar toolbar;
|
||||||
private CircleImageView toolbarAvatar;
|
private CircleImageView toolbarAvatar;
|
||||||
@@ -142,14 +147,24 @@ public class ConversationActivity extends BriarActivity
|
|||||||
private BriarRecyclerView list;
|
private BriarRecyclerView list;
|
||||||
private TextInputView textInputView;
|
private TextInputView textInputView;
|
||||||
|
|
||||||
|
private final ListenableFutureTask<String> contactNameTask =
|
||||||
|
new ListenableFutureTask<>(new Callable<String>() {
|
||||||
|
@Override
|
||||||
|
public String call() throws Exception {
|
||||||
|
Contact c = contactManager.getContact(contactId);
|
||||||
|
contactName = c.getAuthor().getName();
|
||||||
|
return c.getAuthor().getName();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
private final AtomicBoolean contactNameTaskStarted =
|
||||||
|
new AtomicBoolean(false);
|
||||||
|
|
||||||
// Fields that are accessed from background threads must be volatile
|
// Fields that are accessed from background threads must be volatile
|
||||||
@Inject
|
@Inject
|
||||||
volatile ContactManager contactManager;
|
volatile ContactManager contactManager;
|
||||||
@Inject
|
@Inject
|
||||||
volatile MessagingManager messagingManager;
|
volatile MessagingManager messagingManager;
|
||||||
@Inject
|
@Inject
|
||||||
volatile ConversationManager conversationManager;
|
|
||||||
@Inject
|
|
||||||
volatile EventBus eventBus;
|
volatile EventBus eventBus;
|
||||||
@Inject
|
@Inject
|
||||||
volatile SettingsManager settingsManager;
|
volatile SettingsManager settingsManager;
|
||||||
@@ -166,6 +181,8 @@ public class ConversationActivity extends BriarActivity
|
|||||||
|
|
||||||
private volatile ContactId contactId;
|
private volatile ContactId contactId;
|
||||||
@Nullable
|
@Nullable
|
||||||
|
private volatile String contactName;
|
||||||
|
@Nullable
|
||||||
private volatile AuthorId contactAuthorId;
|
private volatile AuthorId contactAuthorId;
|
||||||
@Nullable
|
@Nullable
|
||||||
private volatile GroupId messagingGroupId;
|
private volatile GroupId messagingGroupId;
|
||||||
@@ -194,7 +211,6 @@ public class ConversationActivity extends BriarActivity
|
|||||||
setTransitionName(toolbarAvatar, getAvatarTransitionName(contactId));
|
setTransitionName(toolbarAvatar, getAvatarTransitionName(contactId));
|
||||||
setTransitionName(toolbarStatus, getBulbTransitionName(contactId));
|
setTransitionName(toolbarStatus, getBulbTransitionName(contactId));
|
||||||
|
|
||||||
visitor = new ConversationVisitor(this, this, contactName);
|
|
||||||
adapter = new ConversationAdapter(this, this);
|
adapter = new ConversationAdapter(this, this);
|
||||||
list = findViewById(R.id.conversationView);
|
list = findViewById(R.id.conversationView);
|
||||||
list.setLayoutManager(new LinearLayoutManager(this));
|
list.setLayoutManager(new LinearLayoutManager(this));
|
||||||
@@ -278,9 +294,9 @@ public class ConversationActivity extends BriarActivity
|
|||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
long start = now();
|
long start = now();
|
||||||
if (contactAuthorId == null) {
|
if (contactName == null || contactAuthorId == null) {
|
||||||
Contact contact = contactManager.getContact(contactId);
|
Contact contact = contactManager.getContact(contactId);
|
||||||
contactName.postValue(contact.getAuthor().getName());
|
contactName = contact.getAuthor().getName();
|
||||||
contactAuthorId = contact.getAuthor().getId();
|
contactAuthorId = contact.getAuthor().getId();
|
||||||
}
|
}
|
||||||
logDuration(LOG, "Loading contact", start);
|
logDuration(LOG, "Loading contact", start);
|
||||||
@@ -294,13 +310,12 @@ public class ConversationActivity extends BriarActivity
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// contactAuthorId and contactName are expected to be set
|
|
||||||
private void displayContactDetails() {
|
private void displayContactDetails() {
|
||||||
runOnUiThreadUnlessDestroyed(() -> {
|
runOnUiThreadUnlessDestroyed(() -> {
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
toolbarAvatar.setImageDrawable(
|
toolbarAvatar.setImageDrawable(
|
||||||
new IdenticonDrawable(contactAuthorId.getBytes()));
|
new IdenticonDrawable(contactAuthorId.getBytes()));
|
||||||
toolbarTitle.setText(contactName.getValue());
|
toolbarTitle.setText(contactName);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,9 +343,23 @@ public class ConversationActivity extends BriarActivity
|
|||||||
try {
|
try {
|
||||||
long start = now();
|
long start = now();
|
||||||
Collection<PrivateMessageHeader> headers =
|
Collection<PrivateMessageHeader> headers =
|
||||||
conversationManager.getMessageHeaders(contactId);
|
messagingManager.getMessageHeaders(contactId);
|
||||||
|
Collection<IntroductionMessage> introductions =
|
||||||
|
introductionManager.getIntroductionMessages(contactId);
|
||||||
|
Collection<InvitationMessage> forumInvitations =
|
||||||
|
forumSharingManager.getInvitationMessages(contactId);
|
||||||
|
Collection<InvitationMessage> blogInvitations =
|
||||||
|
blogSharingManager.getInvitationMessages(contactId);
|
||||||
|
Collection<InvitationMessage> groupInvitations =
|
||||||
|
groupInvitationManager.getInvitationMessages(contactId);
|
||||||
|
List<InvitationMessage> invitations = new ArrayList<>(
|
||||||
|
forumInvitations.size() + blogInvitations.size() +
|
||||||
|
groupInvitations.size());
|
||||||
|
invitations.addAll(forumInvitations);
|
||||||
|
invitations.addAll(blogInvitations);
|
||||||
|
invitations.addAll(groupInvitations);
|
||||||
logDuration(LOG, "Loading messages", start);
|
logDuration(LOG, "Loading messages", start);
|
||||||
displayMessages(revision, headers);
|
displayMessages(revision, headers, introductions, invitations);
|
||||||
} catch (NoSuchContactException e) {
|
} catch (NoSuchContactException e) {
|
||||||
finishOnUiThread();
|
finishOnUiThread();
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
@@ -340,12 +369,15 @@ public class ConversationActivity extends BriarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void displayMessages(int revision,
|
private void displayMessages(int revision,
|
||||||
Collection<PrivateMessageHeader> headers) {
|
Collection<PrivateMessageHeader> headers,
|
||||||
|
Collection<IntroductionMessage> introductions,
|
||||||
|
Collection<InvitationMessage> invitations) {
|
||||||
runOnUiThreadUnlessDestroyed(() -> {
|
runOnUiThreadUnlessDestroyed(() -> {
|
||||||
if (revision == adapter.getRevision()) {
|
if (revision == adapter.getRevision()) {
|
||||||
adapter.incrementRevision();
|
adapter.incrementRevision();
|
||||||
textInputView.setSendButtonEnabled(true);
|
textInputView.setSendButtonEnabled(true);
|
||||||
List<ConversationItem> items = createItems(headers);
|
List<ConversationItem> items = createItems(headers,
|
||||||
|
introductions, invitations);
|
||||||
adapter.addAll(items);
|
adapter.addAll(items);
|
||||||
list.showData();
|
list.showData();
|
||||||
// Scroll to the bottom
|
// Scroll to the bottom
|
||||||
@@ -364,34 +396,66 @@ public class ConversationActivity extends BriarActivity
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings("ConstantConditions")
|
||||||
private List<ConversationItem> createItems(
|
private List<ConversationItem> createItems(
|
||||||
Collection<PrivateMessageHeader> headers) {
|
Collection<PrivateMessageHeader> headers,
|
||||||
List<ConversationItem> items = new ArrayList<>(headers.size());
|
Collection<IntroductionMessage> introductions,
|
||||||
for (PrivateMessageHeader h : headers) items.add(h.accept(visitor));
|
Collection<InvitationMessage> invitations) {
|
||||||
|
int size =
|
||||||
|
headers.size() + introductions.size() + invitations.size();
|
||||||
|
List<ConversationItem> items = new ArrayList<>(size);
|
||||||
|
for (PrivateMessageHeader h : headers) {
|
||||||
|
ConversationItem item = ConversationItem.from(h);
|
||||||
|
String body = bodyCache.get(h.getId());
|
||||||
|
if (body == null) loadMessageBody(h.getId());
|
||||||
|
else item.setBody(body);
|
||||||
|
items.add(item);
|
||||||
|
}
|
||||||
|
for (IntroductionMessage m : introductions) {
|
||||||
|
ConversationItem item;
|
||||||
|
if (m instanceof IntroductionRequest) {
|
||||||
|
IntroductionRequest i = (IntroductionRequest) m;
|
||||||
|
item = ConversationItem.from(this, contactName, i);
|
||||||
|
} else {
|
||||||
|
IntroductionResponse i = (IntroductionResponse) m;
|
||||||
|
item = ConversationItem.from(this, contactName, i);
|
||||||
|
}
|
||||||
|
items.add(item);
|
||||||
|
}
|
||||||
|
for (InvitationMessage i : invitations) {
|
||||||
|
ConversationItem item;
|
||||||
|
if (i instanceof InvitationRequest) {
|
||||||
|
InvitationRequest r = (InvitationRequest) i;
|
||||||
|
item = ConversationItem.from(this, contactName, r);
|
||||||
|
} else {
|
||||||
|
InvitationResponse r = (InvitationResponse) i;
|
||||||
|
item = ConversationItem.from(this, contactName, r);
|
||||||
|
}
|
||||||
|
items.add(item);
|
||||||
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadMessageText(MessageId m) {
|
private void loadMessageBody(MessageId m) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
long start = now();
|
long start = now();
|
||||||
String text = messagingManager.getMessageText(m);
|
String body = messagingManager.getMessageBody(m);
|
||||||
logDuration(LOG, "Loading text", start);
|
logDuration(LOG, "Loading body", start);
|
||||||
displayMessageText(m, text);
|
displayMessageBody(m, body);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayMessageText(MessageId m, String text) {
|
private void displayMessageBody(MessageId m, String body) {
|
||||||
runOnUiThreadUnlessDestroyed(() -> {
|
runOnUiThreadUnlessDestroyed(() -> {
|
||||||
textCache.put(m, text);
|
bodyCache.put(m, body);
|
||||||
SparseArray<ConversationItem> messages =
|
SparseArray<ConversationItem> messages =
|
||||||
adapter.getPrivateMessages();
|
adapter.getPrivateMessages();
|
||||||
for (int i = 0; i < messages.size(); i++) {
|
for (int i = 0; i < messages.size(); i++) {
|
||||||
ConversationItem item = messages.valueAt(i);
|
ConversationItem item = messages.valueAt(i);
|
||||||
if (item.getId().equals(m)) {
|
if (item.getId().equals(m)) {
|
||||||
item.setText(text);
|
item.setBody(body);
|
||||||
adapter.notifyItemChanged(messages.keyAt(i));
|
adapter.notifyItemChanged(messages.keyAt(i));
|
||||||
list.scrollToPosition(adapter.getItemCount() - 1);
|
list.scrollToPosition(adapter.getItemCount() - 1);
|
||||||
return;
|
return;
|
||||||
@@ -412,7 +476,9 @@ public class ConversationActivity extends BriarActivity
|
|||||||
PrivateMessageReceivedEvent p = (PrivateMessageReceivedEvent) e;
|
PrivateMessageReceivedEvent p = (PrivateMessageReceivedEvent) e;
|
||||||
if (p.getContactId().equals(contactId)) {
|
if (p.getContactId().equals(contactId)) {
|
||||||
LOG.info("Message received, adding");
|
LOG.info("Message received, adding");
|
||||||
onNewPrivateMessage(p.getMessageHeader());
|
PrivateMessageHeader h = p.getMessageHeader();
|
||||||
|
addConversationItem(ConversationItem.from(h));
|
||||||
|
loadMessageBody(h.getId());
|
||||||
}
|
}
|
||||||
} else if (e instanceof MessagesSentEvent) {
|
} else if (e instanceof MessagesSentEvent) {
|
||||||
MessagesSentEvent m = (MessagesSentEvent) e;
|
MessagesSentEvent m = (MessagesSentEvent) e;
|
||||||
@@ -438,6 +504,38 @@ public class ConversationActivity extends BriarActivity
|
|||||||
LOG.info("Contact disconnected");
|
LOG.info("Contact disconnected");
|
||||||
displayContactOnlineStatus();
|
displayContactOnlineStatus();
|
||||||
}
|
}
|
||||||
|
} else if (e instanceof IntroductionRequestReceivedEvent) {
|
||||||
|
IntroductionRequestReceivedEvent event =
|
||||||
|
(IntroductionRequestReceivedEvent) e;
|
||||||
|
if (event.getContactId().equals(contactId)) {
|
||||||
|
LOG.info("Introduction request received, adding...");
|
||||||
|
IntroductionRequest ir = event.getIntroductionRequest();
|
||||||
|
handleIntroductionRequest(ir);
|
||||||
|
}
|
||||||
|
} else if (e instanceof IntroductionResponseReceivedEvent) {
|
||||||
|
IntroductionResponseReceivedEvent event =
|
||||||
|
(IntroductionResponseReceivedEvent) e;
|
||||||
|
if (event.getContactId().equals(contactId)) {
|
||||||
|
LOG.info("Introduction response received, adding...");
|
||||||
|
IntroductionResponse ir = event.getIntroductionResponse();
|
||||||
|
handleIntroductionResponse(ir);
|
||||||
|
}
|
||||||
|
} else if (e instanceof InvitationRequestReceivedEvent) {
|
||||||
|
InvitationRequestReceivedEvent event =
|
||||||
|
(InvitationRequestReceivedEvent) e;
|
||||||
|
if (event.getContactId().equals(contactId)) {
|
||||||
|
LOG.info("Invitation received, adding...");
|
||||||
|
InvitationRequest ir = event.getRequest();
|
||||||
|
handleInvitationRequest(ir);
|
||||||
|
}
|
||||||
|
} else if (e instanceof InvitationResponseReceivedEvent) {
|
||||||
|
InvitationResponseReceivedEvent event =
|
||||||
|
(InvitationResponseReceivedEvent) e;
|
||||||
|
if (event.getContactId().equals(contactId)) {
|
||||||
|
LOG.info("Invitation response received, adding...");
|
||||||
|
InvitationResponse ir = event.getResponse();
|
||||||
|
handleInvitationResponse(ir);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,33 +548,84 @@ public class ConversationActivity extends BriarActivity
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onNewPrivateMessage(PrivateMessageHeader h) {
|
private void handleIntroductionRequest(IntroductionRequest m) {
|
||||||
runOnUiThreadUnlessDestroyed(() -> {
|
getContactNameTask().addListener(new FutureTaskListener<String>() {
|
||||||
if (h instanceof PrivateRequest || h instanceof PrivateResponse) {
|
@Override
|
||||||
String cName = contactName.getValue();
|
public void onSuccess(String contactName) {
|
||||||
if (cName == null) {
|
runOnUiThreadUnlessDestroyed(() -> {
|
||||||
// Wait for the contact name to be loaded
|
ConversationItem item = ConversationItem
|
||||||
contactName.observe(this, new Observer<String>() {
|
.from(ConversationActivity.this, contactName, m);
|
||||||
@Override
|
addConversationItem(item);
|
||||||
public void onChanged(@Nullable String cName) {
|
});
|
||||||
if (cName != null) {
|
}
|
||||||
addConversationItem(h.accept(visitor));
|
|
||||||
contactName.removeObserver(this);
|
@Override
|
||||||
}
|
public void onFailure(Throwable exception) {
|
||||||
}
|
runOnUiThreadUnlessDestroyed(
|
||||||
});
|
() -> handleDbException((DbException) exception));
|
||||||
} else {
|
|
||||||
addConversationItem(h.accept(visitor));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
addConversationItem(h.accept(visitor));
|
|
||||||
loadMessageText(h.getId());
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void markMessages(Collection<MessageId> messageIds, boolean sent,
|
private void handleIntroductionResponse(IntroductionResponse m) {
|
||||||
boolean seen) {
|
getContactNameTask().addListener(new FutureTaskListener<String>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(String contactName) {
|
||||||
|
runOnUiThreadUnlessDestroyed(() -> {
|
||||||
|
ConversationItem item = ConversationItem
|
||||||
|
.from(ConversationActivity.this, contactName, m);
|
||||||
|
addConversationItem(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable exception) {
|
||||||
|
runOnUiThreadUnlessDestroyed(
|
||||||
|
() -> handleDbException((DbException) exception));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleInvitationRequest(InvitationRequest m) {
|
||||||
|
getContactNameTask().addListener(new FutureTaskListener<String>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(String contactName) {
|
||||||
|
runOnUiThreadUnlessDestroyed(() -> {
|
||||||
|
ConversationItem item = ConversationItem
|
||||||
|
.from(ConversationActivity.this, contactName, m);
|
||||||
|
addConversationItem(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable exception) {
|
||||||
|
runOnUiThreadUnlessDestroyed(
|
||||||
|
() -> handleDbException((DbException) exception));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleInvitationResponse(InvitationResponse m) {
|
||||||
|
getContactNameTask().addListener(new FutureTaskListener<String>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(String contactName) {
|
||||||
|
runOnUiThreadUnlessDestroyed(() -> {
|
||||||
|
ConversationItem item = ConversationItem
|
||||||
|
.from(ConversationActivity.this, contactName, m);
|
||||||
|
addConversationItem(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable exception) {
|
||||||
|
runOnUiThreadUnlessDestroyed(
|
||||||
|
() -> handleDbException((DbException) exception));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void markMessages(Collection<MessageId> messageIds,
|
||||||
|
boolean sent, boolean seen) {
|
||||||
runOnUiThreadUnlessDestroyed(() -> {
|
runOnUiThreadUnlessDestroyed(() -> {
|
||||||
adapter.incrementRevision();
|
adapter.incrementRevision();
|
||||||
Set<MessageId> messages = new HashSet<>(messageIds);
|
Set<MessageId> messages = new HashSet<>(messageIds);
|
||||||
@@ -495,8 +644,8 @@ public class ConversationActivity extends BriarActivity
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSendClick(String text) {
|
public void onSendClick(String text) {
|
||||||
if (text.isEmpty()) return;
|
if (text.equals("")) return;
|
||||||
text = StringUtils.truncateUtf8(text, MAX_PRIVATE_MESSAGE_TEXT_LENGTH);
|
text = StringUtils.truncateUtf8(text, MAX_PRIVATE_MESSAGE_BODY_LENGTH);
|
||||||
long timestamp = System.currentTimeMillis();
|
long timestamp = System.currentTimeMillis();
|
||||||
timestamp = Math.max(timestamp, getMinTimestampForNewMessage());
|
timestamp = Math.max(timestamp, getMinTimestampForNewMessage());
|
||||||
if (messagingGroupId == null) loadGroupId(text, timestamp);
|
if (messagingGroupId == null) loadGroupId(text, timestamp);
|
||||||
@@ -510,12 +659,12 @@ public class ConversationActivity extends BriarActivity
|
|||||||
return item == null ? 0 : item.getTime() + 1;
|
return item == null ? 0 : item.getTime() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadGroupId(String text, long timestamp) {
|
private void loadGroupId(String body, long timestamp) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
messagingGroupId =
|
messagingGroupId =
|
||||||
messagingManager.getConversationId(contactId);
|
messagingManager.getConversationId(contactId);
|
||||||
createMessage(text, timestamp);
|
createMessage(body, timestamp);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
@@ -523,19 +672,18 @@ public class ConversationActivity extends BriarActivity
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createMessage(String text, long timestamp) {
|
private void createMessage(String body, long timestamp) {
|
||||||
cryptoExecutor.execute(() -> {
|
cryptoExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
//noinspection ConstantConditions init in loadGroupId()
|
//noinspection ConstantConditions init in loadGroupId()
|
||||||
storeMessage(privateMessageFactory.createPrivateMessage(
|
storeMessage(privateMessageFactory.createPrivateMessage(
|
||||||
messagingGroupId, timestamp, text), text);
|
messagingGroupId, timestamp, body), body);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {throw new RuntimeException(e);
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void storeMessage(PrivateMessage m, String text) {
|
private void storeMessage(PrivateMessage m, String body) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
long start = now();
|
long start = now();
|
||||||
@@ -545,8 +693,10 @@ public class ConversationActivity extends BriarActivity
|
|||||||
PrivateMessageHeader h = new PrivateMessageHeader(
|
PrivateMessageHeader h = new PrivateMessageHeader(
|
||||||
message.getId(), message.getGroupId(),
|
message.getId(), message.getGroupId(),
|
||||||
message.getTimestamp(), true, false, false, false);
|
message.getTimestamp(), true, false, false, false);
|
||||||
textCache.put(message.getId(), text);
|
ConversationItem item = ConversationItem.from(h);
|
||||||
addConversationItem(h.accept(visitor));
|
item.setBody(body);
|
||||||
|
bodyCache.put(message.getId(), body);
|
||||||
|
addConversationItem(item);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
@@ -673,7 +823,7 @@ public class ConversationActivity extends BriarActivity
|
|||||||
@UiThread
|
@UiThread
|
||||||
@Override
|
@Override
|
||||||
public void respondToRequest(ConversationRequestItem item, boolean accept) {
|
public void respondToRequest(ConversationRequestItem item, boolean accept) {
|
||||||
item.setAnswered();
|
item.setAnswered(true);
|
||||||
int position = adapter.findItemPosition(item);
|
int position = adapter.findItemPosition(item);
|
||||||
if (position != INVALID_POSITION) {
|
if (position != INVALID_POSITION) {
|
||||||
adapter.notifyItemChanged(position, item);
|
adapter.notifyItemChanged(position, item);
|
||||||
@@ -759,11 +909,10 @@ public class ConversationActivity extends BriarActivity
|
|||||||
groupInvitationManager.respondToInvitation(contactId, id, accept);
|
groupInvitationManager.respondToInvitation(contactId, id, accept);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
private ListenableFutureTask<String> getContactNameTask() {
|
||||||
@Override
|
if (!contactNameTaskStarted.getAndSet(true))
|
||||||
public String getText(MessageId m) {
|
runOnDbThread(contactNameTask);
|
||||||
String text = textCache.get(m);
|
return contactNameTask;
|
||||||
if (text == null) loadMessageText(m);
|
|
||||||
return text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,50 @@
|
|||||||
package org.briarproject.briar.android.contact;
|
package org.briarproject.briar.android.contact;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.support.annotation.LayoutRes;
|
import android.support.annotation.LayoutRes;
|
||||||
|
import android.support.annotation.StringRes;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
|
import org.briarproject.briar.R;
|
||||||
|
import org.briarproject.briar.android.contact.ConversationRequestItem.RequestType;
|
||||||
|
import org.briarproject.briar.api.blog.BlogInvitationRequest;
|
||||||
|
import org.briarproject.briar.api.blog.BlogInvitationResponse;
|
||||||
|
import org.briarproject.briar.api.client.BaseMessageHeader;
|
||||||
|
import org.briarproject.briar.api.forum.ForumInvitationRequest;
|
||||||
|
import org.briarproject.briar.api.forum.ForumInvitationResponse;
|
||||||
|
import org.briarproject.briar.api.introduction.IntroductionRequest;
|
||||||
|
import org.briarproject.briar.api.introduction.IntroductionResponse;
|
||||||
|
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
|
||||||
|
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest;
|
||||||
|
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse;
|
||||||
|
import org.briarproject.briar.api.sharing.InvitationRequest;
|
||||||
|
import org.briarproject.briar.api.sharing.InvitationResponse;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.concurrent.NotThreadSafe;
|
import javax.annotation.concurrent.NotThreadSafe;
|
||||||
|
|
||||||
|
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.BLOG;
|
||||||
|
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.FORUM;
|
||||||
|
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.GROUP;
|
||||||
|
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.INTRODUCTION;
|
||||||
|
|
||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
abstract class ConversationItem {
|
abstract class ConversationItem {
|
||||||
|
|
||||||
@Nullable
|
protected @Nullable String body;
|
||||||
protected String text;
|
|
||||||
private final MessageId id;
|
private final MessageId id;
|
||||||
private final GroupId groupId;
|
private final GroupId groupId;
|
||||||
private final long time;
|
private final long time;
|
||||||
private boolean read;
|
private boolean read;
|
||||||
|
|
||||||
ConversationItem(MessageId id, GroupId groupId, @Nullable String text,
|
ConversationItem(MessageId id, GroupId groupId, @Nullable String body,
|
||||||
long time, boolean read) {
|
long time, boolean read) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.groupId = groupId;
|
this.groupId = groupId;
|
||||||
this.text = text;
|
this.body = body;
|
||||||
this.time = time;
|
this.time = time;
|
||||||
this.read = read;
|
this.read = read;
|
||||||
}
|
}
|
||||||
@@ -37,13 +57,13 @@ abstract class ConversationItem {
|
|||||||
return groupId;
|
return groupId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setText(String text) {
|
void setBody(String body) {
|
||||||
this.text = text;
|
this.body = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public String getText() {
|
public String getBody() {
|
||||||
return text;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
long getTime() {
|
long getTime() {
|
||||||
@@ -58,4 +78,216 @@ abstract class ConversationItem {
|
|||||||
|
|
||||||
@LayoutRes
|
@LayoutRes
|
||||||
abstract public int getLayout();
|
abstract public int getLayout();
|
||||||
|
|
||||||
|
static ConversationItem from(PrivateMessageHeader h) {
|
||||||
|
if (h.isLocal()) {
|
||||||
|
return new ConversationMessageOutItem(h);
|
||||||
|
} else {
|
||||||
|
return new ConversationMessageInItem(h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ConversationItem from(Context ctx, String contactName,
|
||||||
|
IntroductionRequest ir) {
|
||||||
|
if (ir.isLocal()) {
|
||||||
|
String text = ctx.getString(R.string.introduction_request_sent,
|
||||||
|
contactName, ir.getName());
|
||||||
|
return new ConversationNoticeOutItem(ir.getMessageId(),
|
||||||
|
ir.getGroupId(), text, ir.getMessage(), ir.getTimestamp(),
|
||||||
|
ir.isSent(), ir.isSeen());
|
||||||
|
} else {
|
||||||
|
String text;
|
||||||
|
if (ir.wasAnswered()) {
|
||||||
|
text = ctx.getString(
|
||||||
|
R.string.introduction_request_answered_received,
|
||||||
|
contactName, ir.getName());
|
||||||
|
} else if (ir.contactExists()){
|
||||||
|
text = ctx.getString(
|
||||||
|
R.string.introduction_request_exists_received,
|
||||||
|
contactName, ir.getName());
|
||||||
|
} else {
|
||||||
|
text = ctx.getString(R.string.introduction_request_received,
|
||||||
|
contactName, ir.getName());
|
||||||
|
}
|
||||||
|
return new ConversationRequestItem(ir.getMessageId(),
|
||||||
|
ir.getGroupId(), INTRODUCTION, ir.getSessionId(), text,
|
||||||
|
ir.getMessage(), ir.getTimestamp(), ir.isRead(), null,
|
||||||
|
ir.wasAnswered(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ConversationItem from(Context ctx, String contactName,
|
||||||
|
IntroductionResponse ir) {
|
||||||
|
if (ir.isLocal()) {
|
||||||
|
String text;
|
||||||
|
if (ir.wasAccepted()) {
|
||||||
|
text = ctx.getString(
|
||||||
|
R.string.introduction_response_accepted_sent,
|
||||||
|
ir.getName());
|
||||||
|
text += "\n\n" + ctx.getString(
|
||||||
|
R.string.introduction_response_accepted_sent_info,
|
||||||
|
ir.getName());
|
||||||
|
} else {
|
||||||
|
text = ctx.getString(
|
||||||
|
R.string.introduction_response_declined_sent,
|
||||||
|
ir.getName());
|
||||||
|
}
|
||||||
|
return new ConversationNoticeOutItem(ir.getMessageId(),
|
||||||
|
ir.getGroupId(), text, null, ir.getTimestamp(), ir.isSent(),
|
||||||
|
ir.isSeen());
|
||||||
|
} else {
|
||||||
|
String text;
|
||||||
|
if (ir.wasAccepted()) {
|
||||||
|
text = ctx.getString(
|
||||||
|
R.string.introduction_response_accepted_received,
|
||||||
|
contactName, ir.getName());
|
||||||
|
} else {
|
||||||
|
if (ir.isIntroducer()) {
|
||||||
|
text = ctx.getString(
|
||||||
|
R.string.introduction_response_declined_received,
|
||||||
|
contactName, ir.getName());
|
||||||
|
} else {
|
||||||
|
text = ctx.getString(
|
||||||
|
R.string.introduction_response_declined_received_by_introducee,
|
||||||
|
contactName, ir.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ConversationNoticeInItem(ir.getMessageId(),
|
||||||
|
ir.getGroupId(), text, null, ir.getTimestamp(),
|
||||||
|
ir.isRead());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ConversationItem from(Context ctx, String contactName,
|
||||||
|
InvitationRequest ir) {
|
||||||
|
if (ir.isLocal()) {
|
||||||
|
String text;
|
||||||
|
if (ir instanceof ForumInvitationRequest) {
|
||||||
|
text = ctx.getString(R.string.forum_invitation_sent,
|
||||||
|
((ForumInvitationRequest) ir).getForumName(),
|
||||||
|
contactName);
|
||||||
|
} else if (ir instanceof BlogInvitationRequest) {
|
||||||
|
text = ctx.getString(R.string.blogs_sharing_invitation_sent,
|
||||||
|
((BlogInvitationRequest) ir).getBlogAuthorName(),
|
||||||
|
contactName);
|
||||||
|
} else if (ir instanceof GroupInvitationRequest) {
|
||||||
|
text = ctx.getString(
|
||||||
|
R.string.groups_invitations_invitation_sent,
|
||||||
|
contactName, ir.getShareable().getName());
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Unknown InvitationRequest");
|
||||||
|
}
|
||||||
|
return new ConversationNoticeOutItem(ir.getId(), ir.getGroupId(),
|
||||||
|
text, ir.getMessage(), ir.getTimestamp(), ir.isSent(),
|
||||||
|
ir.isSeen());
|
||||||
|
} else {
|
||||||
|
String text;
|
||||||
|
RequestType type;
|
||||||
|
if (ir instanceof ForumInvitationRequest) {
|
||||||
|
text = ctx.getString(R.string.forum_invitation_received,
|
||||||
|
contactName,
|
||||||
|
((ForumInvitationRequest) ir).getForumName());
|
||||||
|
type = FORUM;
|
||||||
|
} else if (ir instanceof BlogInvitationRequest) {
|
||||||
|
text = ctx.getString(R.string.blogs_sharing_invitation_received,
|
||||||
|
contactName,
|
||||||
|
((BlogInvitationRequest) ir).getBlogAuthorName());
|
||||||
|
type = BLOG;
|
||||||
|
} else if (ir instanceof GroupInvitationRequest) {
|
||||||
|
text = ctx.getString(
|
||||||
|
R.string.groups_invitations_invitation_received,
|
||||||
|
contactName, ir.getShareable().getName());
|
||||||
|
type = GROUP;
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Unknown InvitationRequest");
|
||||||
|
}
|
||||||
|
return new ConversationRequestItem(ir.getId(),
|
||||||
|
ir.getGroupId(), type, ir.getSessionId(), text,
|
||||||
|
ir.getMessage(), ir.getTimestamp(), ir.isRead(),
|
||||||
|
ir.getShareable().getId(), !ir.isAvailable(),
|
||||||
|
ir.canBeOpened());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ConversationItem from(Context ctx, String contactName,
|
||||||
|
InvitationResponse ir) {
|
||||||
|
@StringRes int res;
|
||||||
|
if (ir.isLocal()) {
|
||||||
|
if (ir.wasAccepted()) {
|
||||||
|
if (ir instanceof ForumInvitationResponse) {
|
||||||
|
res = R.string.forum_invitation_response_accepted_sent;
|
||||||
|
} else if (ir instanceof BlogInvitationResponse) {
|
||||||
|
res = R.string.blogs_sharing_response_accepted_sent;
|
||||||
|
} else if (ir instanceof GroupInvitationResponse) {
|
||||||
|
res = R.string.groups_invitations_response_accepted_sent;
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Unknown InvitationResponse");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ir instanceof ForumInvitationResponse) {
|
||||||
|
res = R.string.forum_invitation_response_declined_sent;
|
||||||
|
} else if (ir instanceof BlogInvitationResponse) {
|
||||||
|
res = R.string.blogs_sharing_response_declined_sent;
|
||||||
|
} else if (ir instanceof GroupInvitationResponse) {
|
||||||
|
res = R.string.groups_invitations_response_declined_sent;
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Unknown InvitationResponse");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String text = ctx.getString(res, contactName);
|
||||||
|
return new ConversationNoticeOutItem(ir.getId(), ir.getGroupId(),
|
||||||
|
text, null, ir.getTimestamp(), ir.isSent(), ir.isSeen());
|
||||||
|
} else {
|
||||||
|
if (ir.wasAccepted()) {
|
||||||
|
if (ir instanceof ForumInvitationResponse) {
|
||||||
|
res = R.string.forum_invitation_response_accepted_received;
|
||||||
|
} else if (ir instanceof BlogInvitationResponse) {
|
||||||
|
res = R.string.blogs_sharing_response_accepted_received;
|
||||||
|
} else if (ir instanceof GroupInvitationResponse) {
|
||||||
|
res = R.string.groups_invitations_response_accepted_received;
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Unknown InvitationResponse");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ir instanceof ForumInvitationResponse) {
|
||||||
|
res = R.string.forum_invitation_response_declined_received;
|
||||||
|
} else if (ir instanceof BlogInvitationResponse) {
|
||||||
|
res = R.string.blogs_sharing_response_declined_received;
|
||||||
|
} else if (ir instanceof GroupInvitationResponse) {
|
||||||
|
res = R.string.groups_invitations_response_declined_received;
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Unknown InvitationResponse");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String text = ctx.getString(res, contactName);
|
||||||
|
return new ConversationNoticeInItem(ir.getId(), ir.getGroupId(),
|
||||||
|
text, null, ir.getTimestamp(), ir.isRead());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method should not be used to display the resulting ConversationItem
|
||||||
|
* in the UI, but only to update list information based on the
|
||||||
|
* BaseMessageHeader.
|
||||||
|
**/
|
||||||
|
static ConversationItem from(Context ctx, BaseMessageHeader h) {
|
||||||
|
if (h instanceof PrivateMessageHeader) {
|
||||||
|
return from((PrivateMessageHeader) h);
|
||||||
|
} else if(h instanceof IntroductionRequest) {
|
||||||
|
return from(ctx, "", (IntroductionRequest) h);
|
||||||
|
} else if(h instanceof IntroductionResponse) {
|
||||||
|
return from(ctx, "", (IntroductionResponse) h);
|
||||||
|
} else if(h instanceof InvitationRequest) {
|
||||||
|
return from(ctx, "", (InvitationRequest) h);
|
||||||
|
} else if(h instanceof InvitationResponse) {
|
||||||
|
return from(ctx, "", (InvitationResponse) h);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Unknown message header");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ class ConversationItemViewHolder extends ViewHolder {
|
|||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
void bind(ConversationItem item) {
|
void bind(ConversationItem item) {
|
||||||
if (item.getText() == null) {
|
if (item.getBody() == null) {
|
||||||
text.setText("\u2026");
|
text.setText("\u2026");
|
||||||
} else {
|
} else {
|
||||||
text.setText(StringUtils.trim(item.getText()));
|
text.setText(StringUtils.trim(item.getBody()));
|
||||||
}
|
}
|
||||||
|
|
||||||
long timestamp = item.getTime();
|
long timestamp = item.getTime();
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.api.messaging.PrivateResponse;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.concurrent.NotThreadSafe;
|
import javax.annotation.concurrent.NotThreadSafe;
|
||||||
@@ -18,17 +17,13 @@ class ConversationNoticeInItem extends ConversationItem {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private final String msgText;
|
private final String msgText;
|
||||||
|
|
||||||
ConversationNoticeInItem(MessageId id, GroupId groupId, String text,
|
ConversationNoticeInItem(MessageId id, GroupId groupId,
|
||||||
@Nullable String msgText, long time, boolean read) {
|
String text, @Nullable String msgText, long time,
|
||||||
|
boolean read) {
|
||||||
super(id, groupId, text, time, read);
|
super(id, groupId, text, time, read);
|
||||||
this.msgText = msgText;
|
this.msgText = msgText;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConversationNoticeInItem(String text, PrivateResponse r) {
|
|
||||||
super(r.getId(), r.getGroupId(), text, r.getTimestamp(), r.isRead());
|
|
||||||
this.msgText = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
String getMsgText() {
|
String getMsgText() {
|
||||||
return msgText;
|
return msgText;
|
||||||
@@ -44,4 +39,5 @@ class ConversationNoticeInItem extends ConversationItem {
|
|||||||
public int getLayout() {
|
public int getLayout() {
|
||||||
return R.layout.list_item_conversation_notice_in;
|
return R.layout.list_item_conversation_notice_in;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,13 +29,13 @@ class ConversationNoticeInViewHolder extends ConversationItemViewHolder {
|
|||||||
ConversationNoticeInItem item =
|
ConversationNoticeInItem item =
|
||||||
(ConversationNoticeInItem) conversationItem;
|
(ConversationNoticeInItem) conversationItem;
|
||||||
|
|
||||||
String text = item.getMsgText();
|
String message = item.getMsgText();
|
||||||
if (StringUtils.isNullOrEmpty(text)) {
|
if (StringUtils.isNullOrEmpty(message)) {
|
||||||
msgText.setVisibility(GONE);
|
msgText.setVisibility(GONE);
|
||||||
layout.setBackgroundResource(R.drawable.notice_in);
|
layout.setBackgroundResource(R.drawable.notice_in);
|
||||||
} else {
|
} else {
|
||||||
msgText.setVisibility(VISIBLE);
|
msgText.setVisibility(VISIBLE);
|
||||||
msgText.setText(StringUtils.trim(text));
|
msgText.setText(StringUtils.trim(message));
|
||||||
layout.setBackgroundResource(R.drawable.notice_in_bottom);
|
layout.setBackgroundResource(R.drawable.notice_in_bottom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package org.briarproject.briar.android.contact;
|
|||||||
import android.support.annotation.LayoutRes;
|
import android.support.annotation.LayoutRes;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.api.messaging.PrivateRequest;
|
|
||||||
import org.briarproject.briar.api.messaging.PrivateResponse;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.concurrent.NotThreadSafe;
|
import javax.annotation.concurrent.NotThreadSafe;
|
||||||
@@ -17,16 +17,11 @@ class ConversationNoticeOutItem extends ConversationOutItem {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private final String msgText;
|
private final String msgText;
|
||||||
|
|
||||||
ConversationNoticeOutItem(String text, PrivateRequest r) {
|
ConversationNoticeOutItem(MessageId id, GroupId groupId,
|
||||||
super(r.getId(), r.getGroupId(), text, r.getTimestamp(), r.isSent(),
|
String text, @Nullable String msgText, long time,
|
||||||
r.isSeen());
|
boolean sent, boolean seen) {
|
||||||
this.msgText = r.getText();
|
super(id, groupId, text, time, sent, seen);
|
||||||
}
|
this.msgText = msgText;
|
||||||
|
|
||||||
ConversationNoticeOutItem(String text, PrivateResponse r) {
|
|
||||||
super(r.getId(), r.getGroupId(), text, r.getTimestamp(), r.isSent(),
|
|
||||||
r.isSeen());
|
|
||||||
this.msgText = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -39,4 +34,5 @@ class ConversationNoticeOutItem extends ConversationOutItem {
|
|||||||
public int getLayout() {
|
public int getLayout() {
|
||||||
return R.layout.list_item_conversation_notice_out;
|
return R.layout.list_item_conversation_notice_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,13 +29,13 @@ class ConversationNoticeOutViewHolder extends ConversationOutItemViewHolder {
|
|||||||
ConversationNoticeOutItem item =
|
ConversationNoticeOutItem item =
|
||||||
(ConversationNoticeOutItem) conversationItem;
|
(ConversationNoticeOutItem) conversationItem;
|
||||||
|
|
||||||
String text = item.getMsgText();
|
String message = item.getMsgText();
|
||||||
if (StringUtils.isNullOrEmpty(text)) {
|
if (StringUtils.isNullOrEmpty(message)) {
|
||||||
msgText.setVisibility(GONE);
|
msgText.setVisibility(GONE);
|
||||||
layout.setBackgroundResource(R.drawable.notice_out);
|
layout.setBackgroundResource(R.drawable.notice_out);
|
||||||
} else {
|
} else {
|
||||||
msgText.setVisibility(VISIBLE);
|
msgText.setVisibility(VISIBLE);
|
||||||
msgText.setText(StringUtils.trim(text));
|
msgText.setText(StringUtils.trim(message));
|
||||||
layout.setBackgroundResource(R.drawable.notice_out_bottom);
|
layout.setBackgroundResource(R.drawable.notice_out_bottom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,9 @@ import android.support.annotation.LayoutRes;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.api.client.SessionId;
|
import org.briarproject.briar.api.client.SessionId;
|
||||||
import org.briarproject.briar.api.messaging.PrivateRequest;
|
|
||||||
import org.briarproject.briar.api.sharing.InvitationRequest;
|
|
||||||
import org.briarproject.briar.api.sharing.Shareable;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.concurrent.NotThreadSafe;
|
import javax.annotation.concurrent.NotThreadSafe;
|
||||||
@@ -17,7 +15,7 @@ import javax.annotation.concurrent.NotThreadSafe;
|
|||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class ConversationRequestItem extends ConversationNoticeInItem {
|
class ConversationRequestItem extends ConversationNoticeInItem {
|
||||||
|
|
||||||
enum RequestType {INTRODUCTION, FORUM, BLOG, GROUP}
|
enum RequestType { INTRODUCTION, FORUM, BLOG, GROUP }
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private final GroupId requestedGroupId;
|
private final GroupId requestedGroupId;
|
||||||
@@ -26,19 +24,17 @@ class ConversationRequestItem extends ConversationNoticeInItem {
|
|||||||
private final boolean canBeOpened;
|
private final boolean canBeOpened;
|
||||||
private boolean answered;
|
private boolean answered;
|
||||||
|
|
||||||
ConversationRequestItem(String text, RequestType type, PrivateRequest r) {
|
ConversationRequestItem(MessageId id, GroupId groupId,
|
||||||
super(r.getId(), r.getGroupId(), text, r.getText(),
|
RequestType requestType, SessionId sessionId, String text,
|
||||||
r.getTimestamp(), r.isRead());
|
@Nullable String msgText, long time, boolean read,
|
||||||
this.requestType = type;
|
@Nullable GroupId requestedGroupId, boolean answered,
|
||||||
this.sessionId = r.getSessionId();
|
boolean canBeOpened) {
|
||||||
this.answered = r.wasAnswered();
|
super(id, groupId, text, msgText, time, read);
|
||||||
if (r instanceof InvitationRequest) {
|
this.requestType = requestType;
|
||||||
this.requestedGroupId = ((Shareable) r.getNameable()).getId();
|
this.sessionId = sessionId;
|
||||||
this.canBeOpened = ((InvitationRequest) r).canBeOpened();
|
this.requestedGroupId = requestedGroupId;
|
||||||
} else {
|
this.answered = answered;
|
||||||
this.requestedGroupId = null;
|
this.canBeOpened = canBeOpened;
|
||||||
this.canBeOpened = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestType getRequestType() {
|
RequestType getRequestType() {
|
||||||
@@ -58,8 +54,8 @@ class ConversationRequestItem extends ConversationNoticeInItem {
|
|||||||
return answered;
|
return answered;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAnswered() {
|
void setAnswered(boolean answered) {
|
||||||
this.answered = true;
|
this.answered = answered;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canBeOpened() {
|
public boolean canBeOpened() {
|
||||||
@@ -71,4 +67,5 @@ class ConversationRequestItem extends ConversationNoticeInItem {
|
|||||||
public int getLayout() {
|
public int getLayout() {
|
||||||
return R.layout.list_item_conversation_request;
|
return R.layout.list_item_conversation_request;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,246 +0,0 @@
|
|||||||
package org.briarproject.briar.android.contact;
|
|
||||||
|
|
||||||
import android.arch.lifecycle.LiveData;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.support.annotation.UiThread;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
|
||||||
import org.briarproject.briar.R;
|
|
||||||
import org.briarproject.briar.api.blog.BlogInvitationRequest;
|
|
||||||
import org.briarproject.briar.api.blog.BlogInvitationResponse;
|
|
||||||
import org.briarproject.briar.api.forum.ForumInvitationRequest;
|
|
||||||
import org.briarproject.briar.api.forum.ForumInvitationResponse;
|
|
||||||
import org.briarproject.briar.api.introduction.IntroductionRequest;
|
|
||||||
import org.briarproject.briar.api.introduction.IntroductionResponse;
|
|
||||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
|
|
||||||
import org.briarproject.briar.api.messaging.PrivateMessageVisitor;
|
|
||||||
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest;
|
|
||||||
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.BLOG;
|
|
||||||
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.FORUM;
|
|
||||||
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.GROUP;
|
|
||||||
import static org.briarproject.briar.android.contact.ConversationRequestItem.RequestType.INTRODUCTION;
|
|
||||||
|
|
||||||
@UiThread
|
|
||||||
@NotNullByDefault
|
|
||||||
class ConversationVisitor implements PrivateMessageVisitor<ConversationItem> {
|
|
||||||
|
|
||||||
private final Context ctx;
|
|
||||||
private final TextCache textCache;
|
|
||||||
private final LiveData<String> contactName;
|
|
||||||
|
|
||||||
ConversationVisitor(Context ctx, TextCache textCache,
|
|
||||||
LiveData<String> contactName) {
|
|
||||||
this.ctx = ctx;
|
|
||||||
this.textCache = textCache;
|
|
||||||
this.contactName = contactName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConversationItem visitPrivateMessageHeader(PrivateMessageHeader h) {
|
|
||||||
ConversationItem item;
|
|
||||||
if (h.isLocal()) item = new ConversationMessageOutItem(h);
|
|
||||||
else item = new ConversationMessageInItem(h);
|
|
||||||
String text = textCache.getText(h.getId());
|
|
||||||
if (text != null) item.setText(text);
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConversationItem visitBlogInvitationRequest(
|
|
||||||
BlogInvitationRequest r) {
|
|
||||||
if (r.isLocal()) {
|
|
||||||
String text = ctx.getString(R.string.blogs_sharing_invitation_sent,
|
|
||||||
r.getName(), contactName.getValue());
|
|
||||||
return new ConversationNoticeOutItem(text, r);
|
|
||||||
} else {
|
|
||||||
String text = ctx.getString(
|
|
||||||
R.string.blogs_sharing_invitation_received,
|
|
||||||
contactName.getValue(), r.getName());
|
|
||||||
return new ConversationRequestItem(text, BLOG, r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConversationItem visitBlogInvitationResponse(
|
|
||||||
BlogInvitationResponse r) {
|
|
||||||
if (r.isLocal()) {
|
|
||||||
String text;
|
|
||||||
if (r.wasAccepted()) {
|
|
||||||
text = ctx.getString(
|
|
||||||
R.string.blogs_sharing_response_accepted_sent,
|
|
||||||
contactName.getValue());
|
|
||||||
} else {
|
|
||||||
text = ctx.getString(
|
|
||||||
R.string.blogs_sharing_response_declined_sent,
|
|
||||||
contactName.getValue());
|
|
||||||
}
|
|
||||||
return new ConversationNoticeOutItem(text, r);
|
|
||||||
} else {
|
|
||||||
String text;
|
|
||||||
if (r.wasAccepted()) {
|
|
||||||
text = ctx.getString(
|
|
||||||
R.string.blogs_sharing_response_accepted_received,
|
|
||||||
contactName.getValue());
|
|
||||||
} else {
|
|
||||||
text = ctx.getString(
|
|
||||||
R.string.blogs_sharing_response_declined_received,
|
|
||||||
contactName.getValue());
|
|
||||||
}
|
|
||||||
return new ConversationNoticeInItem(text, r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConversationItem visitForumInvitationRequest(
|
|
||||||
ForumInvitationRequest r) {
|
|
||||||
if (r.isLocal()) {
|
|
||||||
String text = ctx.getString(R.string.forum_invitation_sent,
|
|
||||||
r.getName(), contactName.getValue());
|
|
||||||
return new ConversationNoticeOutItem(text, r);
|
|
||||||
} else {
|
|
||||||
String text = ctx.getString(
|
|
||||||
R.string.forum_invitation_received,
|
|
||||||
contactName.getValue(), r.getName());
|
|
||||||
return new ConversationRequestItem(text, FORUM, r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConversationItem visitForumInvitationResponse(
|
|
||||||
ForumInvitationResponse r) {
|
|
||||||
if (r.isLocal()) {
|
|
||||||
String text;
|
|
||||||
if (r.wasAccepted()) {
|
|
||||||
text = ctx.getString(
|
|
||||||
R.string.forum_invitation_response_accepted_sent,
|
|
||||||
contactName.getValue());
|
|
||||||
} else {
|
|
||||||
text = ctx.getString(
|
|
||||||
R.string.forum_invitation_response_declined_sent,
|
|
||||||
contactName.getValue());
|
|
||||||
}
|
|
||||||
return new ConversationNoticeOutItem(text, r);
|
|
||||||
} else {
|
|
||||||
String text;
|
|
||||||
if (r.wasAccepted()) {
|
|
||||||
text = ctx.getString(
|
|
||||||
R.string.forum_invitation_response_accepted_received,
|
|
||||||
contactName.getValue());
|
|
||||||
} else {
|
|
||||||
text = ctx.getString(
|
|
||||||
R.string.forum_invitation_response_declined_received,
|
|
||||||
contactName.getValue());
|
|
||||||
}
|
|
||||||
return new ConversationNoticeInItem(text, r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConversationItem visitGroupInvitationRequest(
|
|
||||||
GroupInvitationRequest r) {
|
|
||||||
if (r.isLocal()) {
|
|
||||||
String text = ctx.getString(
|
|
||||||
R.string.groups_invitations_invitation_sent,
|
|
||||||
contactName.getValue(), r.getName());
|
|
||||||
return new ConversationNoticeOutItem(text, r);
|
|
||||||
} else {
|
|
||||||
String text = ctx.getString(
|
|
||||||
R.string.groups_invitations_invitation_received,
|
|
||||||
contactName.getValue(), r.getName());
|
|
||||||
return new ConversationRequestItem(text, GROUP, r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConversationItem visitGroupInvitationResponse(
|
|
||||||
GroupInvitationResponse r) {
|
|
||||||
if (r.isLocal()) {
|
|
||||||
String text;
|
|
||||||
if (r.wasAccepted()) {
|
|
||||||
text = ctx.getString(
|
|
||||||
R.string.groups_invitations_response_accepted_sent,
|
|
||||||
contactName.getValue());
|
|
||||||
} else {
|
|
||||||
text = ctx.getString(
|
|
||||||
R.string.groups_invitations_response_declined_sent,
|
|
||||||
contactName.getValue());
|
|
||||||
}
|
|
||||||
return new ConversationNoticeOutItem(text, r);
|
|
||||||
} else {
|
|
||||||
String text;
|
|
||||||
if (r.wasAccepted()) {
|
|
||||||
text = ctx.getString(
|
|
||||||
R.string.groups_invitations_response_accepted_received,
|
|
||||||
contactName.getValue());
|
|
||||||
} else {
|
|
||||||
text = ctx.getString(
|
|
||||||
R.string.groups_invitations_response_declined_received,
|
|
||||||
contactName.getValue());
|
|
||||||
}
|
|
||||||
return new ConversationNoticeInItem(text, r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConversationItem visitIntroductionRequest(IntroductionRequest r) {
|
|
||||||
if (r.isLocal()) {
|
|
||||||
String text = ctx.getString(R.string.introduction_request_sent,
|
|
||||||
contactName.getValue(), r.getName());
|
|
||||||
return new ConversationNoticeOutItem(text, r);
|
|
||||||
} else {
|
|
||||||
String text = ctx.getString(R.string.introduction_request_received,
|
|
||||||
contactName.getValue(), r.getName());
|
|
||||||
return new ConversationRequestItem(text, INTRODUCTION, r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConversationItem visitIntroductionResponse(IntroductionResponse r) {
|
|
||||||
if (r.isLocal()) {
|
|
||||||
String text;
|
|
||||||
if (r.wasAccepted()) {
|
|
||||||
String introducee = r.getIntroducedAuthor().getName();
|
|
||||||
text = ctx.getString(
|
|
||||||
R.string.introduction_response_accepted_sent,
|
|
||||||
introducee)
|
|
||||||
+ "\n\n" + ctx.getString(
|
|
||||||
R.string.introduction_response_accepted_sent_info,
|
|
||||||
introducee);
|
|
||||||
} else {
|
|
||||||
text = ctx.getString(
|
|
||||||
R.string.introduction_response_declined_sent,
|
|
||||||
r.getIntroducedAuthor().getName());
|
|
||||||
}
|
|
||||||
return new ConversationNoticeOutItem(text, r);
|
|
||||||
} else {
|
|
||||||
String text;
|
|
||||||
if (r.wasAccepted()) {
|
|
||||||
text = ctx.getString(
|
|
||||||
R.string.introduction_response_accepted_received,
|
|
||||||
contactName.getValue(),
|
|
||||||
r.getIntroducedAuthor().getName());
|
|
||||||
} else if (r.isIntroducer()) {
|
|
||||||
text = ctx.getString(
|
|
||||||
R.string.introduction_response_declined_received,
|
|
||||||
contactName.getValue(),
|
|
||||||
r.getIntroducedAuthor().getName());
|
|
||||||
} else {
|
|
||||||
text = ctx.getString(
|
|
||||||
R.string.introduction_response_declined_received_by_introducee,
|
|
||||||
contactName.getValue(),
|
|
||||||
r.getIntroducedAuthor().getName());
|
|
||||||
}
|
|
||||||
return new ConversationNoticeInItem(text, r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TextCache {
|
|
||||||
@Nullable
|
|
||||||
String getText(MessageId m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -33,7 +33,7 @@ import javax.inject.Inject;
|
|||||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||||
import static android.widget.Toast.LENGTH_SHORT;
|
import static android.widget.Toast.LENGTH_SHORT;
|
||||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_SHARE_FORUM;
|
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_SHARE_FORUM;
|
||||||
import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_TEXT_LENGTH;
|
import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -130,8 +130,8 @@ public class ForumActivity extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getMaxTextLength() {
|
protected int getMaxBodyLength() {
|
||||||
return MAX_FORUM_POST_TEXT_LENGTH;
|
return MAX_FORUM_POST_BODY_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -79,15 +79,16 @@ class ForumControllerImpl extends
|
|||||||
ForumPostReceivedEvent f = (ForumPostReceivedEvent) e;
|
ForumPostReceivedEvent f = (ForumPostReceivedEvent) e;
|
||||||
if (f.getGroupId().equals(getGroupId())) {
|
if (f.getGroupId().equals(getGroupId())) {
|
||||||
LOG.info("Forum post received, adding...");
|
LOG.info("Forum post received, adding...");
|
||||||
onForumPostReceived(f.getHeader(), f.getText());
|
onForumPostReceived(f.getHeader(), f.getBody());
|
||||||
}
|
}
|
||||||
} else if (e instanceof ForumInvitationResponseReceivedEvent) {
|
} else if (e instanceof ForumInvitationResponseReceivedEvent) {
|
||||||
ForumInvitationResponseReceivedEvent f =
|
ForumInvitationResponseReceivedEvent f =
|
||||||
(ForumInvitationResponseReceivedEvent) e;
|
(ForumInvitationResponseReceivedEvent) e;
|
||||||
ForumInvitationResponse r = f.getMessageHeader();
|
ForumInvitationResponse r =
|
||||||
|
(ForumInvitationResponse) f.getResponse();
|
||||||
if (r.getShareableId().equals(getGroupId()) && r.wasAccepted()) {
|
if (r.getShareableId().equals(getGroupId()) && r.wasAccepted()) {
|
||||||
LOG.info("Forum invitation was accepted");
|
LOG.info("Forum invitation was accepted");
|
||||||
onForumInvitationAccepted(f.getContactId());
|
onForumInvitationAccepted(r.getContactId());
|
||||||
}
|
}
|
||||||
} else if (e instanceof ContactLeftShareableEvent) {
|
} else if (e instanceof ContactLeftShareableEvent) {
|
||||||
ContactLeftShareableEvent c = (ContactLeftShareableEvent) e;
|
ContactLeftShareableEvent c = (ContactLeftShareableEvent) e;
|
||||||
@@ -109,8 +110,8 @@ class ForumControllerImpl extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String loadMessageText(ForumPostHeader h) throws DbException {
|
protected String loadMessageBody(ForumPostHeader h) throws DbException {
|
||||||
return forumManager.getPostText(h.getId());
|
return forumManager.getPostBody(h.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -137,7 +138,7 @@ class ForumControllerImpl extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createAndStoreMessage(String text,
|
public void createAndStoreMessage(String body,
|
||||||
@Nullable ForumItem parentItem,
|
@Nullable ForumItem parentItem,
|
||||||
ResultExceptionHandler<ForumItem, DbException> handler) {
|
ResultExceptionHandler<ForumItem, DbException> handler) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
@@ -148,7 +149,7 @@ class ForumControllerImpl extends
|
|||||||
clock.currentTimeMillis());
|
clock.currentTimeMillis());
|
||||||
MessageId parentId = parentItem != null ?
|
MessageId parentId = parentItem != null ?
|
||||||
parentItem.getId() : null;
|
parentItem.getId() : null;
|
||||||
createMessage(text, timestamp, parentId, author, handler);
|
createMessage(body, timestamp, parentId, author, handler);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
handler.onException(e);
|
handler.onException(e);
|
||||||
@@ -156,14 +157,14 @@ class ForumControllerImpl extends
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createMessage(String text, long timestamp,
|
private void createMessage(String body, long timestamp,
|
||||||
@Nullable MessageId parentId, LocalAuthor author,
|
@Nullable MessageId parentId, LocalAuthor author,
|
||||||
ResultExceptionHandler<ForumItem, DbException> handler) {
|
ResultExceptionHandler<ForumItem, DbException> handler) {
|
||||||
cryptoExecutor.execute(() -> {
|
cryptoExecutor.execute(() -> {
|
||||||
LOG.info("Creating forum post...");
|
LOG.info("Creating forum post...");
|
||||||
ForumPost msg = forumManager.createLocalPost(getGroupId(), text,
|
ForumPost msg = forumManager.createLocalPost(getGroupId(), body,
|
||||||
timestamp, parentId, author);
|
timestamp, parentId, author);
|
||||||
storePost(msg, text, handler);
|
storePost(msg, body, handler);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,12 +180,12 @@ class ForumControllerImpl extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ForumItem buildItem(ForumPostHeader header, String text) {
|
protected ForumItem buildItem(ForumPostHeader header, String body) {
|
||||||
return new ForumItem(header, text);
|
return new ForumItem(header, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onForumPostReceived(ForumPostHeader h, String text) {
|
private void onForumPostReceived(ForumPostHeader h, String body) {
|
||||||
ForumItem item = buildItem(h, text);
|
ForumItem item = buildItem(h, body);
|
||||||
listener.runOnUiThreadUnlessDestroyed(
|
listener.runOnUiThreadUnlessDestroyed(
|
||||||
() -> listener.onItemReceived(item));
|
() -> listener.onItemReceived(item));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ import javax.annotation.concurrent.NotThreadSafe;
|
|||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
class ForumItem extends ThreadItem {
|
class ForumItem extends ThreadItem {
|
||||||
|
|
||||||
ForumItem(ForumPostHeader h, String text) {
|
ForumItem(ForumPostHeader h, String body) {
|
||||||
super(h.getId(), h.getParentId(), text, h.getTimestamp(), h.getAuthor(),
|
super(h.getId(), h.getParentId(), body, h.getTimestamp(), h.getAuthor(),
|
||||||
h.getAuthorStatus(), h.isRead());
|
h.getAuthorStatus(), h.isRead());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package org.briarproject.briar.android.introduction;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v7.app.ActionBar;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@@ -38,7 +37,7 @@ import static android.view.View.VISIBLE;
|
|||||||
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.Level.WARNING;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_INTRODUCTION_TEXT_LENGTH;
|
import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_REQUEST_MESSAGE_LENGTH;
|
||||||
|
|
||||||
public class IntroductionMessageFragment extends BaseFragment
|
public class IntroductionMessageFragment extends BaseFragment
|
||||||
implements TextInputListener {
|
implements TextInputListener {
|
||||||
@@ -83,8 +82,8 @@ public class IntroductionMessageFragment extends BaseFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
ViewGroup container, Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
|
|
||||||
// change toolbar text
|
// change toolbar text
|
||||||
ActionBar actionBar = introductionActivity.getSupportActionBar();
|
ActionBar actionBar = introductionActivity.getSupportActionBar();
|
||||||
@@ -183,14 +182,14 @@ public class IntroductionMessageFragment extends BaseFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSendClick(@NonNull String text) {
|
public void onSendClick(String text) {
|
||||||
// disable button to prevent accidental double invitations
|
// disable button to prevent accidental double invitations
|
||||||
ui.message.setSendButtonEnabled(false);
|
ui.message.setSendButtonEnabled(false);
|
||||||
|
|
||||||
String txt = ui.message.getText().toString();
|
String msg = ui.message.getText().toString();
|
||||||
if (txt.isEmpty()) txt = null;
|
if (msg.equals("")) msg = null;
|
||||||
else txt = StringUtils.truncateUtf8(txt, MAX_INTRODUCTION_TEXT_LENGTH);
|
else msg = StringUtils.truncateUtf8(msg, MAX_REQUEST_MESSAGE_LENGTH);
|
||||||
makeIntroduction(contact1, contact2, txt);
|
makeIntroduction(contact1, contact2, msg);
|
||||||
|
|
||||||
// don't wait for the introduction to be made before finishing activity
|
// don't wait for the introduction to be made before finishing activity
|
||||||
introductionActivity.hideSoftKeyboard(ui.message);
|
introductionActivity.hideSoftKeyboard(ui.message);
|
||||||
@@ -199,12 +198,12 @@ public class IntroductionMessageFragment extends BaseFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void makeIntroduction(Contact c1, Contact c2,
|
private void makeIntroduction(Contact c1, Contact c2,
|
||||||
@Nullable String text) {
|
@Nullable String msg) {
|
||||||
introductionActivity.runOnDbThread(() -> {
|
introductionActivity.runOnDbThread(() -> {
|
||||||
// actually make the introduction
|
// actually make the introduction
|
||||||
try {
|
try {
|
||||||
long timestamp = System.currentTimeMillis();
|
long timestamp = System.currentTimeMillis();
|
||||||
introductionManager.makeIntroduction(c1, c2, text, timestamp);
|
introductionManager.makeIntroduction(c1, c2, msg, timestamp);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
introductionError();
|
introductionError();
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import android.widget.Toast;
|
|||||||
|
|
||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.UnsupportedVersionException;
|
||||||
import org.briarproject.bramble.api.event.Event;
|
import org.briarproject.bramble.api.event.Event;
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
import org.briarproject.bramble.api.keyagreement.KeyAgreementResult;
|
import org.briarproject.bramble.api.keyagreement.KeyAgreementResult;
|
||||||
@@ -22,7 +23,6 @@ import org.briarproject.bramble.api.keyagreement.KeyAgreementTask;
|
|||||||
import org.briarproject.bramble.api.keyagreement.Payload;
|
import org.briarproject.bramble.api.keyagreement.Payload;
|
||||||
import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
|
import org.briarproject.bramble.api.keyagreement.PayloadEncoder;
|
||||||
import org.briarproject.bramble.api.keyagreement.PayloadParser;
|
import org.briarproject.bramble.api.keyagreement.PayloadParser;
|
||||||
import org.briarproject.bramble.api.keyagreement.UnsupportedVersionException;
|
|
||||||
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementAbortedEvent;
|
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementAbortedEvent;
|
||||||
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementFailedEvent;
|
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementFailedEvent;
|
||||||
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementFinishedEvent;
|
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementFinishedEvent;
|
||||||
@@ -244,14 +244,8 @@ public class KeyAgreementFragment extends BaseEventFragment
|
|||||||
task.connectAndRunProtocol(remotePayload);
|
task.connectAndRunProtocol(remotePayload);
|
||||||
} catch (UnsupportedVersionException e) {
|
} catch (UnsupportedVersionException e) {
|
||||||
reset();
|
reset();
|
||||||
String msg;
|
String msg = getString(R.string.qr_code_unsupported,
|
||||||
if (e.isTooOld()) {
|
getString(R.string.app_name));
|
||||||
msg = getString(R.string.qr_code_too_old,
|
|
||||||
getString(R.string.app_name));
|
|
||||||
} else {
|
|
||||||
msg = getString(R.string.qr_code_too_new,
|
|
||||||
getString(R.string.app_name));
|
|
||||||
}
|
|
||||||
showNextFragment(ContactExchangeErrorFragment.newInstance(msg));
|
showNextFragment(ContactExchangeErrorFragment.newInstance(msg));
|
||||||
} catch (CameraException e) {
|
} catch (CameraException e) {
|
||||||
logCameraExceptionAndFinish(e);
|
logCameraExceptionAndFinish(e);
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
|||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.COMPACTING_DATABASE;
|
|
||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE;
|
||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING_SERVICES;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING_SERVICES;
|
||||||
|
|
||||||
@@ -35,7 +34,7 @@ public class OpenDatabaseActivity extends BriarActivity
|
|||||||
|
|
||||||
private TextView textView;
|
private TextView textView;
|
||||||
private ImageView imageView;
|
private ImageView imageView;
|
||||||
private boolean showingMigration = false, showingCompaction = false;
|
private boolean showingMigration = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle state) {
|
public void onCreate(@Nullable Bundle state) {
|
||||||
@@ -58,7 +57,6 @@ public class OpenDatabaseActivity extends BriarActivity
|
|||||||
finishAndStartApp();
|
finishAndStartApp();
|
||||||
} else {
|
} else {
|
||||||
if (state == MIGRATING_DATABASE) showMigration();
|
if (state == MIGRATING_DATABASE) showMigration();
|
||||||
else if (state == COMPACTING_DATABASE) showCompaction();
|
|
||||||
eventBus.addListener(this);
|
eventBus.addListener(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,8 +75,6 @@ public class OpenDatabaseActivity extends BriarActivity
|
|||||||
runOnUiThreadUnlessDestroyed(this::finishAndStartApp);
|
runOnUiThreadUnlessDestroyed(this::finishAndStartApp);
|
||||||
else if (state == MIGRATING_DATABASE)
|
else if (state == MIGRATING_DATABASE)
|
||||||
runOnUiThreadUnlessDestroyed(this::showMigration);
|
runOnUiThreadUnlessDestroyed(this::showMigration);
|
||||||
else if (state == COMPACTING_DATABASE)
|
|
||||||
runOnUiThreadUnlessDestroyed(this::showCompaction);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,13 +85,6 @@ public class OpenDatabaseActivity extends BriarActivity
|
|||||||
showingMigration = true;
|
showingMigration = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showCompaction() {
|
|
||||||
if (showingCompaction) return;
|
|
||||||
textView.setText(R.string.startup_compact_database);
|
|
||||||
imageView.setImageResource(R.drawable.startup_migration);
|
|
||||||
showingCompaction = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void finishAndStartApp() {
|
private void finishAndStartApp() {
|
||||||
startActivity(new Intent(this, NavDrawerActivity.class));
|
startActivity(new Intent(this, NavDrawerActivity.class));
|
||||||
supportFinishAfterTransition();
|
supportFinishAfterTransition();
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import android.graphics.drawable.ClipDrawable;
|
|||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.LayerDrawable;
|
import android.graphics.drawable.LayerDrawable;
|
||||||
import android.graphics.drawable.ShapeDrawable;
|
import android.graphics.drawable.ShapeDrawable;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
@@ -16,7 +15,6 @@ import static android.graphics.Paint.Style.FILL;
|
|||||||
import static android.graphics.Paint.Style.STROKE;
|
import static android.graphics.Paint.Style.STROKE;
|
||||||
import static android.graphics.drawable.ClipDrawable.HORIZONTAL;
|
import static android.graphics.drawable.ClipDrawable.HORIZONTAL;
|
||||||
import static android.view.Gravity.LEFT;
|
import static android.view.Gravity.LEFT;
|
||||||
import static android.view.Gravity.START;
|
|
||||||
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_STRONG;
|
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_STRONG;
|
||||||
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.bramble.api.crypto.PasswordStrengthEstimator.STRONG;
|
||||||
@@ -37,11 +35,11 @@ public class StrengthMeter extends ProgressBar {
|
|||||||
this(context, null);
|
this(context, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StrengthMeter(Context context, @Nullable AttributeSet attrs) {
|
public StrengthMeter(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs, android.R.attr.progressBarStyleHorizontal);
|
super(context, attrs, android.R.attr.progressBarStyleHorizontal);
|
||||||
bar = new ShapeDrawable();
|
bar = new ShapeDrawable();
|
||||||
bar.getPaint().setColor(RED);
|
bar.getPaint().setColor(RED);
|
||||||
ClipDrawable clip = new ClipDrawable(bar, LEFT & START, HORIZONTAL);
|
ClipDrawable clip = new ClipDrawable(bar, LEFT, HORIZONTAL);
|
||||||
ShapeDrawable background = new ShapeDrawable();
|
ShapeDrawable background = new ShapeDrawable();
|
||||||
Paint p = background.getPaint();
|
Paint p = background.getPaint();
|
||||||
p.setStyle(FILL);
|
p.setStyle(FILL);
|
||||||
@@ -52,7 +50,6 @@ public class StrengthMeter extends ProgressBar {
|
|||||||
Drawable[] layers = new Drawable[] { clip, background };
|
Drawable[] layers = new Drawable[] { clip, background };
|
||||||
setProgressDrawable(new LayerDrawable(layers));
|
setProgressDrawable(new LayerDrawable(layers));
|
||||||
setIndeterminate(false);
|
setIndeterminate(false);
|
||||||
if (isInEditMode()) setStrength(STRONG);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,84 +0,0 @@
|
|||||||
package org.briarproject.briar.android.panic;
|
|
||||||
|
|
||||||
import info.guardianproject.trustedintents.ApkSignaturePin;
|
|
||||||
|
|
||||||
// needs to be public, because TrustedIntents will instantiate
|
|
||||||
public final class FDroidSignaturePin extends ApkSignaturePin {
|
|
||||||
|
|
||||||
public FDroidSignaturePin() {
|
|
||||||
this.fingerprints = new String[] {
|
|
||||||
"927f7e38b6acbecd84e02dace33efa9a7a2f0979750f28f585688ee38b3a4e28"};
|
|
||||||
this.certificates = new byte[][] {
|
|
||||||
{48, -126, 3, 95, 48, -126, 2, 71, -96, 3, 2, 1, 2, 2, 4, 28,
|
|
||||||
-30, 107, -102, 48, 13, 6, 9, 42, -122, 72, -122, -9,
|
|
||||||
13, 1, 1, 11, 5, 0, 48, 96, 49, 11, 48, 9, 6, 3, 85, 4,
|
|
||||||
6, 19, 2, 85, 75, 49, 12, 48, 10, 6, 3, 85, 4, 8, 19, 3,
|
|
||||||
79, 82, 71, 49, 12, 48, 10, 6, 3, 85, 4, 7, 19, 3, 79,
|
|
||||||
82, 71, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10, 102,
|
|
||||||
100, 114, 111, 105, 100, 46, 111, 114, 103, 49, 15, 48,
|
|
||||||
13, 6, 3, 85, 4, 11, 19, 6, 70, 68, 114, 111, 105, 100,
|
|
||||||
49, 15, 48, 13, 6, 3, 85, 4, 3, 19, 6, 70, 68, 114, 111,
|
|
||||||
105, 100, 48, 30, 23, 13, 49, 55, 49, 50, 48, 55, 49,
|
|
||||||
55, 51, 48, 52, 50, 90, 23, 13, 52, 53, 48, 52, 50, 52,
|
|
||||||
49, 55, 51, 48, 52, 50, 90, 48, 96, 49, 11, 48, 9, 6, 3,
|
|
||||||
85, 4, 6, 19, 2, 85, 75, 49, 12, 48, 10, 6, 3, 85, 4, 8,
|
|
||||||
19, 3, 79, 82, 71, 49, 12, 48, 10, 6, 3, 85, 4, 7, 19,
|
|
||||||
3, 79, 82, 71, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10,
|
|
||||||
102, 100, 114, 111, 105, 100, 46, 111, 114, 103, 49, 15,
|
|
||||||
48, 13, 6, 3, 85, 4, 11, 19, 6, 70, 68, 114, 111, 105,
|
|
||||||
100, 49, 15, 48, 13, 6, 3, 85, 4, 3, 19, 6, 70, 68, 114,
|
|
||||||
111, 105, 100, 48, -126, 1, 34, 48, 13, 6, 9, 42, -122,
|
|
||||||
72, -122, -9, 13, 1, 1, 1, 5, 0, 3, -126, 1, 15, 0, 48,
|
|
||||||
-126, 1, 10, 2, -126, 1, 1, 0, -107, -115, -106, 1, -26,
|
|
||||||
72, -105, -99, 62, 3, -55, 34, 99, -112, -68, -20, -115,
|
|
||||||
31, 34, 118, -50, 12, -32, -59, 74, -58, -37, -87, 21,
|
|
||||||
105, 36, -82, 13, -51, 66, 4, 55, -111, 13, -46, -7,
|
|
||||||
-69, -15, 36, 118, -7, 101, -86, 123, -83, -103, 110,
|
|
||||||
116, -54, 112, 46, 12, 96, -76, -48, -70, -33, -81, 52,
|
|
||||||
59, 73, 107, -126, -72, -25, 32, 93, 29, -20, 5, -41,
|
|
||||||
-27, 123, -9, 104, -31, -59, -1, -83, -93, 99, 85, -116,
|
|
||||||
-62, -55, 18, -63, 6, -51, -110, 33, 9, 7, -49, 102,
|
|
||||||
-20, -122, -124, -68, 93, -102, 31, 48, 86, 96, -99,
|
|
||||||
105, -52, 95, 12, 57, 99, 12, -24, 70, 40, -99, -20,
|
|
||||||
-21, -85, -70, -105, 95, 117, -31, 126, -126, -39, 46,
|
|
||||||
-62, 59, -23, -74, 108, -12, -56, -40, -96, 79, -37,
|
|
||||||
-82, 1, 99, -104, 48, -60, 92, 14, 109, 127, -22, 31,
|
|
||||||
115, -27, 108, 9, 92, 118, -45, 103, 117, 57, -50, -82,
|
|
||||||
114, -113, 68, -82, 87, 96, 111, 72, 65, -63, 12, 31,
|
|
||||||
-34, -31, -55, -101, 101, 101, 59, 73, -119, -122, 82,
|
|
||||||
28, 47, -108, -85, 59, 46, 89, -93, -1, 9, -11, -51, 63,
|
|
||||||
-44, 109, -76, -103, -26, -49, -80, 6, 52, -27, 73,
|
|
||||||
-104, 40, 2, -101, -124, 60, -52, -105, -70, -24, -62,
|
|
||||||
88, 38, 53, -99, -92, 31, 119, 26, 79, 60, -124, 25,
|
|
||||||
-115, -89, -115, -109, 0, 6, 122, -78, 116, 82, 3, 39,
|
|
||||||
-67, 45, -43, 17, -39, 2, 3, 1, 0, 1, -93, 33, 48, 31,
|
|
||||||
48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 63, 109, -42,
|
|
||||||
-109, 25, 22, 7, -37, -22, -41, -38, 58, -56, 2, -68,
|
|
||||||
-38, -22, 65, -28, -60, 48, 13, 6, 9, 42, -122, 72,
|
|
||||||
-122, -9, 13, 1, 1, 11, 5, 0, 3, -126, 1, 1, 0, 94, 17,
|
|
||||||
31, 36, 85, -11, 85, 44, 19, -80, -20, -92, -118, 93,
|
|
||||||
40, 45, 96, 31, -3, -37, -110, -96, 102, 81, 61, -74,
|
|
||||||
-125, -117, -112, 58, -47, 17, 78, -18, 111, -116, 26,
|
|
||||||
-91, 73, 100, 84, -99, 21, 87, 73, -106, 108, -51, -125,
|
|
||||||
-21, 119, -88, -78, 2, 82, -109, -64, -9, -86, -112,
|
|
||||||
-115, 66, -86, 46, 71, 107, -65, 96, -102, 47, 35, -45,
|
|
||||||
-126, 33, 34, 121, -25, -85, -121, -56, -42, 22, -1,
|
|
||||||
-95, -86, 81, 100, -70, 113, 104, -73, 22, -19, 79, -19,
|
|
||||||
52, 62, 42, 76, -112, 94, -34, 42, -57, -75, -90, -58,
|
|
||||||
118, 127, -106, -39, 108, -56, -79, 103, -33, 22, 3, 47,
|
|
||||||
103, -76, -81, 53, -22, -44, -26, -102, 63, -99, 39, 38,
|
|
||||||
-108, 75, 33, 10, 25, -110, -125, -115, 114, -69, 73,
|
|
||||||
-112, 36, 74, 77, -82, -44, 29, -123, -8, -117, 71,
|
|
||||||
-105, 15, -109, 51, 22, 4, 80, 1, 43, 118, 121, -113,
|
|
||||||
-70, 83, -56, 82, -110, 4, -63, 16, -57, 126, -70, 81,
|
|
||||||
73, 61, 2, -61, 24, -14, -10, 4, -21, 90, 24, 66, 41,
|
|
||||||
-57, -60, -113, -18, -54, -1, 103, -75, 32, -64, 67,
|
|
||||||
103, 109, -79, -12, -113, -27, 114, 89, 116, 115, -13,
|
|
||||||
-123, -70, 61, -41, -46, -118, 29, -105, -97, -75, 39,
|
|
||||||
-51, 60, 88, 125, 55, -46, -95, 52, 57, 52, -115, 80,
|
|
||||||
44, 109, 119, -116, -62, -77, -74, -88, 41, 57, -65,
|
|
||||||
-71, -115, -67, 23, 66, -21, 56, 51, -91, 109}};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.briar.android.panic;
|
package org.briarproject.briar.android.panic;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -21,39 +22,34 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import info.guardianproject.panic.Panic;
|
||||||
import info.guardianproject.panic.PanicResponder;
|
import info.guardianproject.panic.PanicResponder;
|
||||||
|
|
||||||
import static android.app.Activity.RESULT_CANCELED;
|
|
||||||
import static android.app.Activity.RESULT_OK;
|
|
||||||
import static android.content.Intent.ACTION_VIEW;
|
|
||||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
|
||||||
import static info.guardianproject.panic.Panic.PACKAGE_NAME_NONE;
|
|
||||||
|
|
||||||
public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
||||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
public static final String KEY_LOCK = "pref_key_lock";
|
public static final String KEY_LOCK = "pref_key_lock";
|
||||||
public static final String KEY_PANIC_APP = "pref_key_panic_app";
|
public static final String KEY_PANIC_APP = "pref_key_panic_app";
|
||||||
public static final String KEY_PURGE = "pref_key_purge";
|
public static final String KEY_PURGE = "pref_key_purge";
|
||||||
|
public static final String KEY_UNINSTALL = "pref_key_uninstall";
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(PanicPreferencesFragment.class.getName());
|
Logger.getLogger(PanicPreferencesFragment.class.getName());
|
||||||
|
|
||||||
private PackageManager pm;
|
private PackageManager pm;
|
||||||
private SwitchPreference lockPref, purgePref;
|
private SwitchPreference lockPref, purgePref, uninstallPref;
|
||||||
private ListPreference panicAppPref;
|
private ListPreference panicAppPref;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreatePreferences(Bundle bundle, String s) {
|
public void onCreatePreferences(Bundle bundle, String s) {
|
||||||
addPreferencesFromResource(R.xml.panic_preferences);
|
addPreferencesFromResource(R.xml.panic_preferences);
|
||||||
}
|
|
||||||
|
|
||||||
private void updatePreferences() {
|
|
||||||
pm = getActivity().getPackageManager();
|
pm = getActivity().getPackageManager();
|
||||||
|
|
||||||
lockPref = (SwitchPreference) findPreference(KEY_LOCK);
|
lockPref = (SwitchPreference) findPreference(KEY_LOCK);
|
||||||
panicAppPref = (ListPreference) findPreference(KEY_PANIC_APP);
|
panicAppPref = (ListPreference) findPreference(KEY_PANIC_APP);
|
||||||
purgePref = (SwitchPreference) findPreference(KEY_PURGE);
|
purgePref = (SwitchPreference) findPreference(KEY_PURGE);
|
||||||
|
uninstallPref = (SwitchPreference) findPreference(KEY_UNINSTALL);
|
||||||
|
|
||||||
// check for connect/disconnect intents from panic trigger apps
|
// check for connect/disconnect intents from panic trigger apps
|
||||||
if (PanicResponder.checkForDisconnectIntent(getActivity())) {
|
if (PanicResponder.checkForDisconnectIntent(getActivity())) {
|
||||||
@@ -80,7 +76,7 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
|||||||
ArrayList<CharSequence> entries = new ArrayList<>();
|
ArrayList<CharSequence> entries = new ArrayList<>();
|
||||||
ArrayList<CharSequence> entryValues = new ArrayList<>();
|
ArrayList<CharSequence> entryValues = new ArrayList<>();
|
||||||
entries.add(0, getString(R.string.panic_app_setting_none));
|
entries.add(0, getString(R.string.panic_app_setting_none));
|
||||||
entryValues.add(0, PACKAGE_NAME_NONE);
|
entryValues.add(0, Panic.PACKAGE_NAME_NONE);
|
||||||
|
|
||||||
for (ResolveInfo resolveInfo : PanicResponder.resolveTriggerApps(pm)) {
|
for (ResolveInfo resolveInfo : PanicResponder.resolveTriggerApps(pm)) {
|
||||||
if (resolveInfo.activityInfo == null)
|
if (resolveInfo.activityInfo == null)
|
||||||
@@ -89,21 +85,28 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
|||||||
entryValues.add(resolveInfo.activityInfo.packageName);
|
entryValues.add(resolveInfo.activityInfo.packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
panicAppPref.setEntries(entries.toArray(new CharSequence[0]));
|
panicAppPref.setEntries(
|
||||||
panicAppPref.setEntryValues(entryValues.toArray(new CharSequence[0]));
|
entries.toArray(new CharSequence[entries.size()]));
|
||||||
panicAppPref.setDefaultValue(PACKAGE_NAME_NONE);
|
panicAppPref.setEntryValues(
|
||||||
|
entryValues.toArray(new CharSequence[entryValues.size()]));
|
||||||
|
panicAppPref.setDefaultValue(Panic.PACKAGE_NAME_NONE);
|
||||||
|
|
||||||
panicAppPref.setOnPreferenceChangeListener((preference, newValue) -> {
|
panicAppPref.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||||
String packageName = (String) newValue;
|
String packageName = (String) newValue;
|
||||||
PanicResponder.setTriggerPackageName(getActivity(), packageName);
|
PanicResponder.setTriggerPackageName(getActivity(), packageName);
|
||||||
showPanicApp(packageName);
|
showPanicApp(packageName);
|
||||||
|
|
||||||
if (packageName.equals(PACKAGE_NAME_NONE)) {
|
if (packageName.equals(Panic.PACKAGE_NAME_NONE)) {
|
||||||
|
lockPref.setEnabled(false);
|
||||||
purgePref.setChecked(false);
|
purgePref.setChecked(false);
|
||||||
purgePref.setEnabled(false);
|
purgePref.setEnabled(false);
|
||||||
getActivity().setResult(RESULT_CANCELED);
|
uninstallPref.setChecked(false);
|
||||||
|
uninstallPref.setEnabled(false);
|
||||||
|
getActivity().setResult(Activity.RESULT_CANCELED);
|
||||||
} else {
|
} else {
|
||||||
|
lockPref.setEnabled(true);
|
||||||
purgePref.setEnabled(true);
|
purgePref.setEnabled(true);
|
||||||
|
uninstallPref.setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -111,18 +114,16 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
|||||||
|
|
||||||
if (entries.size() <= 1) {
|
if (entries.size() <= 1) {
|
||||||
panicAppPref.setOnPreferenceClickListener(preference -> {
|
panicAppPref.setOnPreferenceClickListener(preference -> {
|
||||||
Intent intent = new Intent(ACTION_VIEW);
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||||
intent.setData(Uri.parse(
|
intent.setData(Uri.parse(
|
||||||
"market://details?id=info.guardianproject.ripple"));
|
"market://details?id=info.guardianproject.ripple"));
|
||||||
intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
if (intent.resolveActivity(getActivity().getPackageManager())
|
if (intent.resolveActivity(getActivity().getPackageManager())
|
||||||
!= null) {
|
!= null) {
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
panicAppPref.setOnPreferenceClickListener(null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +132,6 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
|||||||
super.onStart();
|
super.onStart();
|
||||||
getPreferenceScreen().getSharedPreferences()
|
getPreferenceScreen().getSharedPreferences()
|
||||||
.registerOnSharedPreferenceChangeListener(this);
|
.registerOnSharedPreferenceChangeListener(this);
|
||||||
updatePreferences();
|
|
||||||
showPanicApp(PanicResponder.getTriggerPackageName(getActivity()));
|
showPanicApp(PanicResponder.getTriggerPackageName(getActivity()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,30 +145,44 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
|||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
|
||||||
String key) {
|
String key) {
|
||||||
// enable locking if purging gets enabled
|
if (key.equals(KEY_PURGE)) {
|
||||||
if (key.equals(KEY_PURGE) &&
|
// enable locking if purging gets enabled
|
||||||
sharedPreferences.getBoolean(KEY_PURGE, false)) {
|
if (sharedPreferences.getBoolean(KEY_PURGE, false)) {
|
||||||
lockPref.setChecked(true);
|
lockPref.setChecked(true);
|
||||||
|
}
|
||||||
|
// disable uninstall if purging gets disabled
|
||||||
|
else {
|
||||||
|
uninstallPref.setChecked(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// disable purging if locking gets disabled
|
// enable purging and locking if uninstall gets enabled
|
||||||
|
if (key.equals(KEY_UNINSTALL) &&
|
||||||
|
sharedPreferences.getBoolean(KEY_UNINSTALL, false)) {
|
||||||
|
lockPref.setChecked(true);
|
||||||
|
purgePref.setChecked(true);
|
||||||
|
}
|
||||||
|
// disable purging and uninstalling if locking gets disabled
|
||||||
if (key.equals(KEY_LOCK) &&
|
if (key.equals(KEY_LOCK) &&
|
||||||
!sharedPreferences.getBoolean(KEY_LOCK, true)) {
|
!sharedPreferences.getBoolean(KEY_LOCK, true)) {
|
||||||
purgePref.setChecked(false);
|
purgePref.setChecked(false);
|
||||||
|
uninstallPref.setChecked(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showPanicApp(String triggerPackageName) {
|
private void showPanicApp(String triggerPackageName) {
|
||||||
if (TextUtils.isEmpty(triggerPackageName)
|
if (TextUtils.isEmpty(triggerPackageName)
|
||||||
|| triggerPackageName.equals(PACKAGE_NAME_NONE)) {
|
|| triggerPackageName.equals(Panic.PACKAGE_NAME_NONE)) {
|
||||||
// no panic app set
|
// no panic app set
|
||||||
panicAppPref.setValue(PACKAGE_NAME_NONE);
|
panicAppPref.setValue(Panic.PACKAGE_NAME_NONE);
|
||||||
panicAppPref
|
panicAppPref
|
||||||
.setSummary(getString(R.string.panic_app_setting_summary));
|
.setSummary(getString(R.string.panic_app_setting_summary));
|
||||||
panicAppPref.setIcon(
|
panicAppPref.setIcon(
|
||||||
android.R.drawable.ic_menu_close_clear_cancel);
|
android.R.drawable.ic_menu_close_clear_cancel);
|
||||||
|
|
||||||
// disable destructive panic actions
|
// disable panic actions
|
||||||
|
lockPref.setEnabled(false);
|
||||||
purgePref.setEnabled(false);
|
purgePref.setEnabled(false);
|
||||||
|
uninstallPref.setEnabled(false);
|
||||||
} else {
|
} else {
|
||||||
// display connected panic app
|
// display connected panic app
|
||||||
try {
|
try {
|
||||||
@@ -178,13 +192,15 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
|||||||
panicAppPref.setIcon(
|
panicAppPref.setIcon(
|
||||||
pm.getApplicationIcon(triggerPackageName));
|
pm.getApplicationIcon(triggerPackageName));
|
||||||
|
|
||||||
// enable destructive panic actions
|
// enable panic actions
|
||||||
|
lockPref.setEnabled(true);
|
||||||
purgePref.setEnabled(true);
|
purgePref.setEnabled(true);
|
||||||
|
uninstallPref.setEnabled(true);
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
// revert back to no app, just to be safe
|
// revert back to no app, just to be safe
|
||||||
PanicResponder.setTriggerPackageName(getActivity(),
|
PanicResponder.setTriggerPackageName(getActivity(),
|
||||||
PACKAGE_NAME_NONE);
|
Panic.PACKAGE_NAME_NONE);
|
||||||
showPanicApp(PACKAGE_NAME_NONE);
|
showPanicApp(Panic.PACKAGE_NAME_NONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,10 +209,10 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
|||||||
DialogInterface.OnClickListener okListener = (dialog, which) -> {
|
DialogInterface.OnClickListener okListener = (dialog, which) -> {
|
||||||
PanicResponder.setTriggerPackageName(getActivity());
|
PanicResponder.setTriggerPackageName(getActivity());
|
||||||
showPanicApp(PanicResponder.getTriggerPackageName(getActivity()));
|
showPanicApp(PanicResponder.getTriggerPackageName(getActivity()));
|
||||||
getActivity().setResult(RESULT_OK);
|
getActivity().setResult(Activity.RESULT_OK);
|
||||||
};
|
};
|
||||||
DialogInterface.OnClickListener cancelListener = (dialog, which) -> {
|
DialogInterface.OnClickListener cancelListener = (dialog, which) -> {
|
||||||
getActivity().setResult(RESULT_CANCELED);
|
getActivity().setResult(Activity.RESULT_CANCELED);
|
||||||
getActivity().finish();
|
getActivity().finish();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.briarproject.briar.android.panic;
|
|||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.preference.PreferenceManager;
|
import android.support.v7.preference.PreferenceManager;
|
||||||
@@ -10,6 +11,7 @@ import org.briarproject.bramble.api.account.AccountManager;
|
|||||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
import org.briarproject.briar.android.activity.BriarActivity;
|
import org.briarproject.briar.android.activity.BriarActivity;
|
||||||
|
import org.iilab.IilabEngineeringRSA2048Pin;
|
||||||
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@@ -20,8 +22,10 @@ import info.guardianproject.panic.Panic;
|
|||||||
import info.guardianproject.panic.PanicResponder;
|
import info.guardianproject.panic.PanicResponder;
|
||||||
import info.guardianproject.trustedintents.TrustedIntents;
|
import info.guardianproject.trustedintents.TrustedIntents;
|
||||||
|
|
||||||
|
import static android.content.Intent.ACTION_DELETE;
|
||||||
import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_LOCK;
|
import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_LOCK;
|
||||||
import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_PURGE;
|
import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_PURGE;
|
||||||
|
import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_UNINSTALL;
|
||||||
|
|
||||||
public class PanicResponderActivity extends BriarActivity {
|
public class PanicResponderActivity extends BriarActivity {
|
||||||
|
|
||||||
@@ -40,8 +44,8 @@ public class PanicResponderActivity extends BriarActivity {
|
|||||||
TrustedIntents trustedIntents = TrustedIntents.get(this);
|
TrustedIntents trustedIntents = TrustedIntents.get(this);
|
||||||
// Guardian Project Ripple
|
// Guardian Project Ripple
|
||||||
trustedIntents.addTrustedSigner(GuardianProjectRSA4096.class);
|
trustedIntents.addTrustedSigner(GuardianProjectRSA4096.class);
|
||||||
// F-Droid
|
// Amnesty International's Panic Button, made by iilab.org
|
||||||
trustedIntents.addTrustedSigner(FDroidSignaturePin.class);
|
trustedIntents.addTrustedSigner(IilabEngineeringRSA2048Pin.class);
|
||||||
|
|
||||||
Intent intent = trustedIntents.getIntentFromTrustedSender(this);
|
Intent intent = trustedIntents.getIntentFromTrustedSender(this);
|
||||||
if (intent != null) {
|
if (intent != null) {
|
||||||
@@ -56,16 +60,23 @@ public class PanicResponderActivity extends BriarActivity {
|
|||||||
LOG.info("Panic Trigger came from connected app");
|
LOG.info("Panic Trigger came from connected app");
|
||||||
|
|
||||||
// Performing panic responses
|
// Performing panic responses
|
||||||
if (sharedPref.getBoolean(KEY_PURGE, false)) {
|
if (sharedPref.getBoolean(KEY_UNINSTALL, false)) {
|
||||||
LOG.info("Purging all data...");
|
LOG.info("Purging all data...");
|
||||||
deleteAllData();
|
deleteAllData();
|
||||||
|
|
||||||
|
LOG.info("Uninstalling...");
|
||||||
|
Intent uninstall = new Intent(ACTION_DELETE);
|
||||||
|
uninstall.setData(
|
||||||
|
Uri.parse("package:" + getPackageName()));
|
||||||
|
startActivity(uninstall);
|
||||||
|
} else if (sharedPref.getBoolean(KEY_PURGE, false)) {
|
||||||
|
LOG.info("Purging all data...");
|
||||||
|
deleteAllData();
|
||||||
|
} else if (sharedPref.getBoolean(KEY_LOCK, true)) {
|
||||||
|
LOG.info("Signing out...");
|
||||||
|
signOut(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// non-destructive actions are allowed by non-connected trusted apps
|
|
||||||
if (sharedPref.getBoolean(KEY_LOCK, true)) {
|
|
||||||
LOG.info("Signing out...");
|
|
||||||
signOut(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ import javax.inject.Inject;
|
|||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_GROUP_INVITE;
|
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_GROUP_INVITE;
|
||||||
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_TEXT_LENGTH;
|
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -179,8 +179,8 @@ public class GroupActivity extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getMaxTextLength() {
|
protected int getMaxBodyLength() {
|
||||||
return MAX_GROUP_POST_TEXT_LENGTH;
|
return MAX_GROUP_POST_BODY_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class GroupControllerImpl extends
|
|||||||
GroupMessageAddedEvent g = (GroupMessageAddedEvent) e;
|
GroupMessageAddedEvent g = (GroupMessageAddedEvent) e;
|
||||||
if (!g.isLocal() && g.getGroupId().equals(getGroupId())) {
|
if (!g.isLocal() && g.getGroupId().equals(getGroupId())) {
|
||||||
LOG.info("Group message received, adding...");
|
LOG.info("Group message received, adding...");
|
||||||
GroupMessageItem item = buildItem(g.getHeader(), g.getText());
|
GroupMessageItem item = buildItem(g.getHeader(), g.getBody());
|
||||||
listener.runOnUiThreadUnlessDestroyed(
|
listener.runOnUiThreadUnlessDestroyed(
|
||||||
() -> listener.onItemReceived(item));
|
() -> listener.onItemReceived(item));
|
||||||
}
|
}
|
||||||
@@ -99,10 +99,11 @@ class GroupControllerImpl extends
|
|||||||
} else if (e instanceof GroupInvitationResponseReceivedEvent) {
|
} else if (e instanceof GroupInvitationResponseReceivedEvent) {
|
||||||
GroupInvitationResponseReceivedEvent g =
|
GroupInvitationResponseReceivedEvent g =
|
||||||
(GroupInvitationResponseReceivedEvent) e;
|
(GroupInvitationResponseReceivedEvent) e;
|
||||||
GroupInvitationResponse r = g.getMessageHeader();
|
GroupInvitationResponse r =
|
||||||
|
(GroupInvitationResponse) g.getResponse();
|
||||||
if (getGroupId().equals(r.getShareableId()) && r.wasAccepted()) {
|
if (getGroupId().equals(r.getShareableId()) && r.wasAccepted()) {
|
||||||
listener.runOnUiThreadUnlessDestroyed(
|
listener.runOnUiThreadUnlessDestroyed(
|
||||||
() -> listener.onInvitationAccepted(g.getContactId()));
|
() -> listener.onInvitationAccepted(r.getContactId()));
|
||||||
}
|
}
|
||||||
} else if (e instanceof GroupDissolvedEvent) {
|
} else if (e instanceof GroupDissolvedEvent) {
|
||||||
GroupDissolvedEvent g = (GroupDissolvedEvent) e;
|
GroupDissolvedEvent g = (GroupDissolvedEvent) e;
|
||||||
@@ -124,13 +125,13 @@ class GroupControllerImpl extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String loadMessageText(GroupMessageHeader header)
|
protected String loadMessageBody(GroupMessageHeader header)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
if (header instanceof JoinMessageHeader) {
|
if (header instanceof JoinMessageHeader) {
|
||||||
// will be looked up later
|
// will be looked up later
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return privateGroupManager.getMessageText(header.getId());
|
return privateGroupManager.getMessageBody(header.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -159,7 +160,7 @@ class GroupControllerImpl extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createAndStoreMessage(String text,
|
public void createAndStoreMessage(String body,
|
||||||
@Nullable GroupMessageItem parentItem,
|
@Nullable GroupMessageItem parentItem,
|
||||||
ResultExceptionHandler<GroupMessageItem, DbException> handler) {
|
ResultExceptionHandler<GroupMessageItem, DbException> handler) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
@@ -173,7 +174,7 @@ class GroupControllerImpl extends
|
|||||||
long timestamp = count.getLatestMsgTime();
|
long timestamp = count.getLatestMsgTime();
|
||||||
if (parentItem != null) parentId = parentItem.getId();
|
if (parentItem != null) parentId = parentItem.getId();
|
||||||
timestamp = max(clock.currentTimeMillis(), timestamp + 1);
|
timestamp = max(clock.currentTimeMillis(), timestamp + 1);
|
||||||
createMessage(text, timestamp, parentId, author, previousMsgId,
|
createMessage(body, timestamp, parentId, author, previousMsgId,
|
||||||
handler);
|
handler);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
@@ -182,7 +183,7 @@ class GroupControllerImpl extends
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createMessage(String text, long timestamp,
|
private void createMessage(String body, long timestamp,
|
||||||
@Nullable MessageId parentId, LocalAuthor author,
|
@Nullable MessageId parentId, LocalAuthor author,
|
||||||
MessageId previousMsgId,
|
MessageId previousMsgId,
|
||||||
ResultExceptionHandler<GroupMessageItem, DbException> handler) {
|
ResultExceptionHandler<GroupMessageItem, DbException> handler) {
|
||||||
@@ -190,8 +191,8 @@ class GroupControllerImpl extends
|
|||||||
LOG.info("Creating group message...");
|
LOG.info("Creating group message...");
|
||||||
GroupMessage msg = groupMessageFactory
|
GroupMessage msg = groupMessageFactory
|
||||||
.createGroupMessage(getGroupId(), timestamp,
|
.createGroupMessage(getGroupId(), timestamp,
|
||||||
parentId, author, text, previousMsgId);
|
parentId, author, body, previousMsgId);
|
||||||
storePost(msg, text, handler);
|
storePost(msg, body, handler);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,11 +209,11 @@ class GroupControllerImpl extends
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected GroupMessageItem buildItem(GroupMessageHeader header,
|
protected GroupMessageItem buildItem(GroupMessageHeader header,
|
||||||
String text) {
|
String body) {
|
||||||
if (header instanceof JoinMessageHeader) {
|
if (header instanceof JoinMessageHeader) {
|
||||||
return new JoinMessageItem((JoinMessageHeader) header, text);
|
return new JoinMessageItem((JoinMessageHeader) header, body);
|
||||||
}
|
}
|
||||||
return new GroupMessageItem(header, text);
|
return new GroupMessageItem(header, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -18,6 +18,6 @@ public interface CreateGroupController
|
|||||||
ResultExceptionHandler<GroupId, DbException> result);
|
ResultExceptionHandler<GroupId, DbException> result);
|
||||||
|
|
||||||
void sendInvitation(GroupId g, Collection<ContactId> contacts,
|
void sendInvitation(GroupId g, Collection<ContactId> contacts,
|
||||||
String text, ResultExceptionHandler<Void, DbException> result);
|
String message, ResultExceptionHandler<Void, DbException> result);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendInvitation(GroupId g, Collection<ContactId> contactIds,
|
public void sendInvitation(GroupId g, Collection<ContactId> contactIds,
|
||||||
String text, ResultExceptionHandler<Void, DbException> handler) {
|
String message, ResultExceptionHandler<Void, DbException> handler) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
LocalAuthor localAuthor = identityManager.getLocalAuthor();
|
LocalAuthor localAuthor = identityManager.getLocalAuthor();
|
||||||
@@ -135,7 +135,7 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
|||||||
// Continue
|
// Continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
signInvitations(g, localAuthor, contacts, text, handler);
|
signInvitations(g, localAuthor, contacts, message, handler);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
handler.onException(e);
|
handler.onException(e);
|
||||||
@@ -144,7 +144,7 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void signInvitations(GroupId g, LocalAuthor localAuthor,
|
private void signInvitations(GroupId g, LocalAuthor localAuthor,
|
||||||
Collection<Contact> contacts, String text,
|
Collection<Contact> contacts, String message,
|
||||||
ResultExceptionHandler<Void, DbException> handler) {
|
ResultExceptionHandler<Void, DbException> handler) {
|
||||||
cryptoExecutor.execute(() -> {
|
cryptoExecutor.execute(() -> {
|
||||||
long timestamp = clock.currentTimeMillis();
|
long timestamp = clock.currentTimeMillis();
|
||||||
@@ -155,20 +155,20 @@ class CreateGroupControllerImpl extends ContactSelectorControllerImpl
|
|||||||
contexts.add(new InvitationContext(c.getId(), timestamp,
|
contexts.add(new InvitationContext(c.getId(), timestamp,
|
||||||
signature));
|
signature));
|
||||||
}
|
}
|
||||||
sendInvitations(g, contexts, text, handler);
|
sendInvitations(g, contexts, message, handler);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendInvitations(GroupId g,
|
private void sendInvitations(GroupId g,
|
||||||
Collection<InvitationContext> contexts, String text,
|
Collection<InvitationContext> contexts, String message,
|
||||||
ResultExceptionHandler<Void, DbException> handler) {
|
ResultExceptionHandler<Void, DbException> handler) {
|
||||||
runOnDbThread(() -> {
|
runOnDbThread(() -> {
|
||||||
try {
|
try {
|
||||||
String txt = text.isEmpty() ? null : text;
|
String msg = message.isEmpty() ? null : message;
|
||||||
for (InvitationContext context : contexts) {
|
for (InvitationContext context : contexts) {
|
||||||
try {
|
try {
|
||||||
groupInvitationManager.sendInvitation(g,
|
groupInvitationManager.sendInvitation(g,
|
||||||
context.contactId, txt, context.timestamp,
|
context.contactId, msg, context.timestamp,
|
||||||
context.signature);
|
context.signature);
|
||||||
} catch (NoSuchContactException e) {
|
} catch (NoSuchContactException e) {
|
||||||
// Continue
|
// Continue
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import java.util.Collection;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_TEXT_LENGTH;
|
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_MSG_LENGTH;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -55,10 +55,10 @@ public class GroupInviteActivity extends ContactSelectorActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onButtonClick(String text) {
|
public boolean onButtonClick(String message) {
|
||||||
if (groupId == null)
|
if (groupId == null)
|
||||||
throw new IllegalStateException("GroupId was not initialized");
|
throw new IllegalStateException("GroupId was not initialized");
|
||||||
controller.sendInvitation(groupId, contacts, text,
|
controller.sendInvitation(groupId, contacts, message,
|
||||||
new UiResultExceptionHandler<Void, DbException>(this) {
|
new UiResultExceptionHandler<Void, DbException>(this) {
|
||||||
@Override
|
@Override
|
||||||
public void onResultUi(Void result) {
|
public void onResultUi(Void result) {
|
||||||
@@ -76,7 +76,7 @@ public class GroupInviteActivity extends ContactSelectorActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaximumTextLength() {
|
public int getMaximumMessageLength() {
|
||||||
return MAX_GROUP_INVITATION_TEXT_LENGTH;
|
return MAX_GROUP_INVITATION_MSG_LENGTH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import android.support.annotation.NonNull;
|
|||||||
import org.acra.collector.CrashReportData;
|
import org.acra.collector.CrashReportData;
|
||||||
import org.acra.sender.ReportSender;
|
import org.acra.sender.ReportSender;
|
||||||
import org.acra.sender.ReportSenderException;
|
import org.acra.sender.ReportSenderException;
|
||||||
|
import org.acra.util.JSONReportBuilder.JSONReportException;
|
||||||
import org.briarproject.bramble.api.reporting.DevReporter;
|
import org.briarproject.bramble.api.reporting.DevReporter;
|
||||||
import org.briarproject.bramble.util.AndroidUtils;
|
import org.briarproject.bramble.util.AndroidUtils;
|
||||||
import org.briarproject.briar.android.AndroidComponent;
|
import org.briarproject.briar.android.AndroidComponent;
|
||||||
@@ -33,7 +34,12 @@ public class BriarReportSender implements ReportSender {
|
|||||||
@NonNull CrashReportData errorContent)
|
@NonNull CrashReportData errorContent)
|
||||||
throws ReportSenderException {
|
throws ReportSenderException {
|
||||||
component.inject(this);
|
component.inject(this);
|
||||||
String crashReport = errorContent.toJSON().toString();
|
String crashReport;
|
||||||
|
try {
|
||||||
|
crashReport = errorContent.toJSON().toString();
|
||||||
|
} catch (JSONReportException e) {
|
||||||
|
throw new ReportSenderException("Couldn't create JSON", e);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
File reportDir = AndroidUtils.getReportDir(ctx);
|
File reportDir = AndroidUtils.getReportDir(ctx);
|
||||||
String reportId = errorContent.getProperty(REPORT_ID);
|
String reportId = errorContent.getProperty(REPORT_ID);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user