Compare commits

..

27 Commits

Author SHA1 Message Date
Torsten Grote
1a9fe070b0 DO NOT MERGE: Return fake image attachements in MessagingManager 2019-03-06 09:51:33 -03:00
akwizgran
144ea0c2fc Merge branch '875-sharing-status-screen-updates' into 'master'
Update memberlists while they are open

Closes #875

See merge request briar/briar!1048
2019-02-28 13:27:19 +00:00
Torsten Grote
a917ebdc76 [android] Close memberlist or sharing status screen when group was left 2019-02-28 09:25:18 -03:00
Torsten Grote
2a389c74dc [android] when sharing a forum or blog, add peers to list while it is open 2019-02-28 09:25:08 -03:00
Torsten Grote
ef16d096f1 [android] add group members to memberlist when they join 2019-02-28 09:25:08 -03:00
akwizgran
679455888b Merge branch '833-ui-reference' into 'master'
Don't pass UI classes to the core, use events instead

See merge request briar/briar!1044
2019-02-28 11:11:14 +00:00
akwizgran
d4372ddae7 Merge branch 'headless-document-build' into 'master'
Briar Headless: Document build process

See merge request briar/briar!1042
2019-02-28 11:10:24 +00:00
Nico Alt
c3ef990a94 Briar Headless: Document build process 2019-02-27 21:27:04 +01:00
Torsten Grote
9422ba2718 Don't pass UI classes to the core, use events instead
This removed the ContactExchangeListener in favor of new events
2019-02-27 13:55:33 -03:00
akwizgran
8343f5c2db Merge branch 'objective-c' into 'master'
Remove Objective C from code styles

See merge request briar/briar!1051
2019-02-27 13:42:08 +00:00
akwizgran
371c7efb04 Merge branch '1106-memberlist-button' into 'master'
Move group memberlist button to overflow menu

See merge request briar/briar!1052
2019-02-27 13:40:19 +00:00
Torsten Grote
92d67645ab [android] move group memberlist button to overflow menu 2019-02-27 10:25:41 -03:00
Torsten Grote
a20e868970 Remove Objective C from code styles 2019-02-27 10:14:22 -03:00
akwizgran
dd853f6718 Merge branch '1475-status-bar-return-transition' into 'master'
Show the status bar when finishing ImageActivity

See merge request briar/briar!1036
2019-02-27 13:11:29 +00:00
akwizgran
16a8ad996a Merge branch '869-remove-group-button' into 'master'
[android] Fix private group status text over remove button

Closes #869

See merge request briar/briar!1047
2019-02-27 11:36:06 +00:00
akwizgran
e27885f0c8 Merge branch '850-initial-group-sharing-status' into 'master'
Update group sharing status when creator joins group

Closes #850

See merge request briar/briar!1046
2019-02-27 11:34:55 +00:00
Torsten Grote
f6ef48bf90 [android] Fix private group status text over remove button 2019-02-26 11:38:17 -03:00
Torsten Grote
e282ca763d [android] Update group sharing status when creator joins group 2019-02-26 11:29:23 -03:00
Torsten Grote
71016382dc Merge branch 'tor-0.3.5.8' into 'master'
Upgrade Tor to 0.3.5.8

See merge request briar/briar!1045
2019-02-26 13:15:22 +00:00
akwizgran
d004933fae Upgrade Tor to 0.3.5.8. 2019-02-26 12:39:47 +00:00
akwizgran
37512c50d8 Merge branch '1497-foreground-permission' into 'master'
Add FOREGROUND_SERVICE permission (needed when targeting higher API level)

See merge request briar/briar!1041
2019-02-21 10:30:10 +00:00
Torsten Grote
0b61a5d40a Add FOREGROUND_SERVICE permission (needed when targeting higher API level) 2019-02-20 11:00:15 -03:00
akwizgran
5dd320f282 Merge branch '1498-meek' into 'master'
Use the pluggable transport meek lite where obfs4 is blocked

Closes #1498 and #1418

See merge request briar/briar!1040
2019-02-19 17:37:13 +00:00
akwizgran
2a21db5fb6 Merge branch 'tor-0.3.5.7' into 'master'
Upgrade Tor to 0.3.5.7

See merge request briar/briar!1039
2019-02-19 16:37:30 +00:00
Torsten Grote
b023593a2c Use the pluggable transport meek lite where obfs4 is blocked 2019-02-19 12:49:22 -03:00
Torsten Grote
5ccf2cae1f Upgrade Tor to 0.3.5.7 2019-02-19 11:09:45 -03:00
Torsten Grote
c2cb89ab73 [android] show the status bar when finishing ImageActivity
to prevent visible jump in exit transition.
2019-02-13 16:54:16 -02:00
51 changed files with 372 additions and 288 deletions

View File

@@ -39,31 +39,6 @@
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<Objective-C-extensions>
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
</file>
<class>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
</class>
<extensions>
<pair source="cpp" header="h" fileNamingConvention="NONE" />
<pair source="c" header="h" fileNamingConvention="NONE" />
</extensions>
</Objective-C-extensions>
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
</XML>

View File

@@ -30,8 +30,8 @@ configurations {
dependencies {
implementation project(path: ':bramble-core', configuration: 'default')
tor 'org.briarproject:tor-android:0.3.4.8@zip'
tor 'org.briarproject:obfs4proxy-android:0.0.7@zip'
tor 'org.briarproject:tor-android:0.3.5.8@zip'
tor 'org.briarproject:obfs4proxy-android:0.0.9@zip'
annotationProcessor 'com.google.dagger:dagger-compiler:2.19'

View File

@@ -68,8 +68,8 @@ dependencyVerification {
'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:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
'org.briarproject:obfs4proxy-android:0.0.7:obfs4proxy-android-0.0.7.zip:abdfb5d889d848de9bf214f9276abbf454808a505b870819eccc9a9e985bf617',
'org.briarproject:tor-android:0.3.4.8:tor-android-0.3.4.8.zip:989a0352d9d8d8172cd6c2137654e165e5d2beb10ed1211bab3814e224ad1926',
'org.briarproject:obfs4proxy-android:0.0.9:obfs4proxy-android-0.0.9.zip:9b7e9181535ea8d8bbe8ae6338e08cf4c5fc1e357a779393e0ce49586d459ae0',
'org.briarproject:tor-android:0.3.5.8:tor-android-0.3.5.8.zip:42a13a6f185be1a62f42e3f30ce66a3c099ac5ec890a65e7593111b65b44a54a',
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
'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',

View File

@@ -1,20 +0,0 @@
package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface ContactExchangeListener {
void contactExchangeSucceeded(Author remoteAuthor);
/**
* The exchange failed because the contact already exists.
*/
void duplicateContact(Author remoteAuthor);
/**
* A general failure.
*/
void contactExchangeFailed();
}

View File

@@ -41,8 +41,7 @@ public interface ContactExchangeTask {
/**
* Exchanges contact information with a remote peer.
*/
void startExchange(ContactExchangeListener listener,
LocalAuthor localAuthor, SecretKey masterSecret,
void startExchange(LocalAuthor localAuthor, SecretKey masterSecret,
DuplexTransportConnection conn, TransportId transportId,
boolean alice);
}

View File

@@ -0,0 +1,32 @@
package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
@NotNullByDefault
public class ContactExchangeFailedEvent extends Event {
@Nullable
private final Author duplicateRemoteAuthor;
public ContactExchangeFailedEvent(@Nullable Author duplicateRemoteAuthor) {
this.duplicateRemoteAuthor = duplicateRemoteAuthor;
}
public ContactExchangeFailedEvent() {
this(null);
}
@Nullable
public Author getDuplicateRemoteAuthor() {
return duplicateRemoteAuthor;
}
public boolean wasDuplicateContact() {
return duplicateRemoteAuthor != null;
}
}

View File

@@ -0,0 +1,20 @@
package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public class ContactExchangeSucceededEvent extends Event {
private final Author remoteAuthor;
public ContactExchangeSucceededEvent(Author remoteAuthor) {
this.remoteAuthor = remoteAuthor;
}
public Author getRemoteAuthor() {
return remoteAuthor;
}
}

View File

@@ -25,7 +25,6 @@ import org.briarproject.bramble.api.transport.KeySetId;
import org.briarproject.bramble.api.transport.TransportKeys;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
@@ -151,8 +150,6 @@ public interface DatabaseComponent {
boolean containsLocalAuthor(Transaction txn, AuthorId local)
throws DbException;
int countFakes(Transaction txn, List<byte[]> ids) throws DbException;
/**
* Deletes the message with the given ID. Unlike
* {@link #removeMessage(Transaction, MessageId)}, the message ID,

View File

@@ -2,10 +2,11 @@ package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.contact.ContactExchangeListener;
import org.briarproject.bramble.api.contact.ContactExchangeTask;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.contact.event.ContactExchangeFailedEvent;
import org.briarproject.bramble.api.contact.event.ContactExchangeSucceededEvent;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.data.BdfDictionary;
@@ -13,6 +14,7 @@ import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.db.ContactExistsException;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
@@ -63,6 +65,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
private final ClientHelper clientHelper;
private final RecordReaderFactory recordReaderFactory;
private final RecordWriterFactory recordWriterFactory;
private final EventBus eventBus;
private final Clock clock;
private final ConnectionManager connectionManager;
private final ContactManager contactManager;
@@ -71,7 +74,6 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
private final StreamReaderFactory streamReaderFactory;
private final StreamWriterFactory streamWriterFactory;
private volatile ContactExchangeListener listener;
private volatile LocalAuthor localAuthor;
private volatile DuplexTransportConnection conn;
private volatile TransportId transportId;
@@ -81,8 +83,9 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
@Inject
ContactExchangeTaskImpl(DatabaseComponent db, ClientHelper clientHelper,
RecordReaderFactory recordReaderFactory,
RecordWriterFactory recordWriterFactory, Clock clock,
ConnectionManager connectionManager, ContactManager contactManager,
RecordWriterFactory recordWriterFactory, EventBus eventBus,
Clock clock, ConnectionManager connectionManager,
ContactManager contactManager,
TransportPropertyManager transportPropertyManager,
CryptoComponent crypto, StreamReaderFactory streamReaderFactory,
StreamWriterFactory streamWriterFactory) {
@@ -90,6 +93,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
this.clientHelper = clientHelper;
this.recordReaderFactory = recordReaderFactory;
this.recordWriterFactory = recordWriterFactory;
this.eventBus = eventBus;
this.clock = clock;
this.connectionManager = connectionManager;
this.contactManager = contactManager;
@@ -100,11 +104,9 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
}
@Override
public void startExchange(ContactExchangeListener listener,
LocalAuthor localAuthor, SecretKey masterSecret,
public void startExchange(LocalAuthor localAuthor, SecretKey masterSecret,
DuplexTransportConnection conn, TransportId transportId,
boolean alice) {
this.listener = listener;
this.localAuthor = localAuthor;
this.conn = conn;
this.transportId = transportId;
@@ -123,8 +125,8 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
out = conn.getWriter().getOutputStream();
} catch (IOException e) {
logException(LOG, WARNING, e);
listener.contactExchangeFailed();
tryToClose(conn);
eventBus.broadcast(new ContactExchangeFailedEvent());
return;
}
@@ -134,7 +136,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
localProperties = transportPropertyManager.getLocalProperties();
} catch (DbException e) {
logException(LOG, WARNING, e);
listener.contactExchangeFailed();
eventBus.broadcast(new ContactExchangeFailedEvent());
tryToClose(conn);
return;
}
@@ -196,7 +198,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
}
} catch (IOException e) {
logException(LOG, WARNING, e);
listener.contactExchangeFailed();
eventBus.broadcast(new ContactExchangeFailedEvent());
tryToClose(conn);
return;
}
@@ -204,7 +206,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
// Verify the contact's signature
if (!verify(remoteInfo.author, remoteNonce, remoteInfo.signature)) {
LOG.warning("Invalid signature");
listener.contactExchangeFailed();
eventBus.broadcast(new ContactExchangeFailedEvent());
tryToClose(conn);
return;
}
@@ -221,15 +223,17 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
conn);
// Pseudonym exchange succeeded
LOG.info("Pseudonym exchange succeeded");
listener.contactExchangeSucceeded(remoteInfo.author);
eventBus.broadcast(
new ContactExchangeSucceededEvent(remoteInfo.author));
} catch (ContactExistsException e) {
logException(LOG, WARNING, e);
tryToClose(conn);
listener.duplicateContact(remoteInfo.author);
eventBus.broadcast(
new ContactExchangeFailedEvent(remoteInfo.author));
} catch (DbException e) {
logException(LOG, WARNING, e);
tryToClose(conn);
listener.contactExchangeFailed();
eventBus.broadcast(new ContactExchangeFailedEvent());
}
}

View File

@@ -28,7 +28,6 @@ import org.briarproject.bramble.api.transport.KeySetId;
import org.briarproject.bramble.api.transport.TransportKeys;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
@@ -189,8 +188,6 @@ interface Database<T> {
boolean containsVisibleMessage(T txn, ContactId c, MessageId m)
throws DbException;
int countFakes(T txn, List<byte[]> ids) throws DbException;
/**
* Returns the number of messages offered by the given contact.
* <p/>

View File

@@ -313,13 +313,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
return db.containsLocalAuthor(txn, local);
}
@Override
public int countFakes(Transaction transaction, List<byte[]> ids)
throws DbException {
T txn = unbox(transaction);
return db.countFakes(txn, ids);
}
@Override
public void deleteMessage(Transaction transaction, MessageId m)
throws DbException {

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.db;
import org.briarproject.bramble.api.UniqueId;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.crypto.SecretKey;
@@ -48,7 +47,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
@@ -94,8 +92,6 @@ abstract class JdbcDatabase implements Database<Connection> {
private static final int OFFSET_CURR = 0;
private static final int OFFSET_NEXT = 1;
private static final int NUM_FAKES = 32 * 1024;
private static final String CREATE_SETTINGS =
"CREATE TABLE settings"
+ " (namespace _STRING NOT NULL,"
@@ -289,20 +285,6 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " REFERENCES contacts (contactId)"
+ " ON DELETE CASCADE)";
// In H2 the MEMORY keyword creates a persistent table with in-memory
// indexes, which must be dropped and recreated when reopening the database.
// In HyperSQL it creates a persistent table that's entirely cached in
// memory, which is the default. Dropping and recreating indexes is
// unnecessary.
private static final String CREATE_FAKES =
"CREATE MEMORY TABLE fakes (fakeId _HASH NOT NULL)";
private static final String DROP_INDEX_FAKES_BY_FAKE_ID =
"DROP INDEX IF EXISTS fakesByFakeId";
private static final String INDEX_FAKES_BY_FAKE_ID =
"CREATE INDEX fakesByFakeId ON fakes (fakeId)";
private static final String INDEX_CONTACTS_BY_AUTHOR_ID =
"CREATE INDEX IF NOT EXISTS contactsByAuthorId"
+ " ON contacts (authorId)";
@@ -394,16 +376,6 @@ abstract class JdbcDatabase implements Database<Connection> {
txn = startTransaction();
try {
storeLastCompacted(txn);
createInMemoryIndexes(txn);
commitTransaction(txn);
} catch (DbException e) {
abortTransaction(txn);
throw e;
}
} else {
txn = startTransaction();
try {
createInMemoryIndexes(txn);
commitTransaction(txn);
} catch (DbException e) {
abortTransaction(txn);
@@ -489,7 +461,6 @@ abstract class JdbcDatabase implements Database<Connection> {
private void createTables(Connection txn) throws DbException {
Statement s = null;
PreparedStatement ps = null;
try {
s = txn.createStatement();
s.executeUpdate(dbTypes.replaceTypes(CREATE_SETTINGS));
@@ -506,29 +477,9 @@ abstract class JdbcDatabase implements Database<Connection> {
s.executeUpdate(dbTypes.replaceTypes(CREATE_TRANSPORTS));
s.executeUpdate(dbTypes.replaceTypes(CREATE_OUTGOING_KEYS));
s.executeUpdate(dbTypes.replaceTypes(CREATE_INCOMING_KEYS));
s.executeUpdate(dbTypes.replaceTypes(CREATE_FAKES));
s.close();
Random random = new Random();
long start = now();
ps = txn.prepareStatement("INSERT INTO fakes (fakeId) VALUES (?)");
int inserted = 0;
while (inserted < NUM_FAKES) {
int batchSize = Math.min(1024, NUM_FAKES - inserted);
for (int i = 0; i < batchSize; i++) {
byte[] id = new byte[UniqueId.LENGTH];
random.nextBytes(id);
ps.setBytes(1, id);
ps.addBatch();
}
ps.executeBatch();
inserted += batchSize;
}
ps.close();
LOG.info("Inserting " + NUM_FAKES + " fakes took "
+ (now() - start) + " ms");
} catch (SQLException e) {
tryToClose(s, LOG, WARNING);
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@@ -550,21 +501,6 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
private void createInMemoryIndexes(Connection txn) throws DbException {
Statement s = null;
try {
long start = now();
s = txn.createStatement();
s.executeUpdate(dbTypes.replaceTypes(DROP_INDEX_FAKES_BY_FAKE_ID));
s.executeUpdate(dbTypes.replaceTypes(INDEX_FAKES_BY_FAKE_ID));
s.close();
LOG.info("Indexing fakes took " + (now() - start) + " ms");
} catch (SQLException e) {
tryToClose(s, LOG, WARNING);
throw new DbException(e);
}
}
@Override
public Connection startTransaction() throws DbException {
Connection txn;
@@ -1217,41 +1153,6 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public int countFakes(Connection txn, List<byte[]> ids)
throws DbException {
if (ids.isEmpty()) return 0;
PreparedStatement ps = null;
ResultSet rs = null;
try {
long start = now();
StringBuilder sb = new StringBuilder();
sb.append("SELECT COUNT (fakeId) FROM fakes WHERE fakeId IN (?");
for (int i = 1; i < ids.size(); i++) {
sb.append(",?");
}
sb.append(')');
String sql = sb.toString();
ps = txn.prepareStatement(sql);
for (int i = 0; i < ids.size(); i++) {
ps.setBytes(i + 1, ids.get(i));
}
rs = ps.executeQuery();
if (!rs.next()) throw new DbException();
int count = rs.getInt(1);
if (rs.next()) throw new DbException();
rs.close();
ps.close();
LOG.info("Counting " + ids.size() + " fakes took "
+ (now() - start) + " ms, found " + count);
return count;
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@Override
public int countOfferedMessages(Connection txn, ContactId c)
throws DbException {

View File

@@ -17,16 +17,24 @@ public interface CircumventionProvider {
String[] BLOCKED = {"CN", "IR", "EG", "BY", "TR", "SY", "VE"};
/**
* Countries where vanilla bridge connection are likely to work.
* Countries where obfs4 bridge connection are likely to work.
* Should be a subset of {@link #BLOCKED}.
*/
String[] BRIDGES = { "EG", "BY", "TR", "SY", "VE" };
String[] BRIDGES = { "CN", "IR", "EG", "BY", "TR", "SY", "VE" };
/**
* Countries where obfs4 bridges won't work and meek is needed.
* Should be a subset of {@link #BRIDGES}.
*/
String[] NEEDS_MEEK = {"CN", "IR"};
boolean isTorProbablyBlocked(String countryCode);
boolean doBridgesWork(String countryCode);
boolean needsMeek(String countryCode);
@IoExecutor
List<String> getBridges();
List<String> getBridges(boolean meek);
}

View File

@@ -22,6 +22,8 @@ class CircumventionProviderImpl implements CircumventionProvider {
new HashSet<>(asList(BLOCKED));
private static final Set<String> BRIDGES_WORK_IN_COUNTRIES =
new HashSet<>(asList(BRIDGES));
private static final Set<String> BRIDGES_NEED_MEEK =
new HashSet<>(asList(NEEDS_MEEK));
@Nullable
private volatile List<String> bridges = null;
@@ -40,9 +42,14 @@ class CircumventionProviderImpl implements CircumventionProvider {
return BRIDGES_WORK_IN_COUNTRIES.contains(countryCode);
}
@Override
public boolean needsMeek(String countryCode) {
return BRIDGES_NEED_MEEK.contains(countryCode);
}
@Override
@IoExecutor
public List<String> getBridges() {
public List<String> getBridges(boolean useMeek) {
List<String> bridges = this.bridges;
if (bridges != null) return new ArrayList<>(bridges);
@@ -53,6 +60,8 @@ class CircumventionProviderImpl implements CircumventionProvider {
bridges = new ArrayList<>();
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
boolean isMeekBridge = line.startsWith("Bridge meek");
if (useMeek && !isMeekBridge || !useMeek && isMeekBridge) continue;
if (!line.startsWith("#")) bridges.add(line);
}
scanner.close();

View File

@@ -470,13 +470,19 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (!enable) callback.transportDisabled();
}
private void enableBridges(boolean enable) throws IOException {
private void enableBridges(boolean enable, boolean needsMeek)
throws IOException {
if (enable) {
Collection<String> conf = new ArrayList<>();
conf.add("UseBridges 1");
conf.add("ClientTransportPlugin obfs4 exec " +
obfs4File.getAbsolutePath());
conf.addAll(circumventionProvider.getBridges());
if (needsMeek) {
conf.add("ClientTransportPlugin meek_lite exec " +
obfs4File.getAbsolutePath());
} else {
conf.add("ClientTransportPlugin obfs4 exec " +
obfs4File.getAbsolutePath());
}
conf.addAll(circumventionProvider.getBridges(needsMeek));
controlConnection.setConf(conf);
} else {
controlConnection.setConf("UseBridges", "0");
@@ -716,12 +722,17 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
enableNetwork(false);
} else if (network == PREF_TOR_NETWORK_WITH_BRIDGES ||
(automatic && bridgesWork)) {
LOG.info("Enabling network, using bridges");
enableBridges(true);
if (circumventionProvider.needsMeek(country)) {
LOG.info("Enabling network, using meek bridges");
enableBridges(true, true);
} else {
LOG.info("Enabling network, using obfs4 bridges");
enableBridges(true, false);
}
enableNetwork(true);
} else {
LOG.info("Enabling network, not using bridges");
enableBridges(false);
enableBridges(false, false);
enableNetwork(true);
}
if (online && wifi && charging) {

View File

@@ -1,4 +1,5 @@
Bridge obfs4 78.46.188.239:37356 5A2D2F4158D0453E00C7C176978D3F41D69C45DB cert=3c0SwxpOisbohNxEc4tb875RVW8eOu1opRTVXJhafaKA/PNNtI7ElQIVOVZg1AdL5bxGCw iat-mode=0
Bridge obfs4 52.15.78.72:9443 02069A3C5362476936B62BA6F5ACC41ABD573A9B cert=ijYG/OKc7kqu2YzKNFfeXN7/BG2BOgfEP2KyYEiGDQthnHbsOiTWHeIG0WJVW+BckzDgKw iat-mode=0
Bridge obfs4 13.58.29.242:9443 0C58939A77DA6B6B29D4B5236A75865659607AE0 cert=OylWIEHb/ezpq1zWxW0sgKRn+9ARH2eOcQOZ8/Gew+4l+oKOhQ2jUX/Y+FSl61JorXZUWA iat-mode=0
Bridge obfs4 45.33.37.112:9443 60A609BB4ABE8D46E634AE81ED29ADAB7776B399 cert=t5v19WmNv5Sc2YPNr8RQids365W7MY8zJwQVkOxBjUMFomMWARDzsbYpcWLLcw0J9Gm+BQ iat-mode=0
Bridge obfs4 45.33.37.112:9443 60A609BB4ABE8D46E634AE81ED29ADAB7776B399 cert=t5v19WmNv5Sc2YPNr8RQids365W7MY8zJwQVkOxBjUMFomMWARDzsbYpcWLLcw0J9Gm+BQ iat-mode=0
Bridge meek_lite 0.0.2.0:2 97700DFE9F483596DDA6264C4D7DF7641E1E39CE url=https://meek.azureedge.net/ front=ajax.aspnetcdn.com

View File

@@ -131,19 +131,6 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertTrue(testDir.mkdirs());
}
@Test
public void testFakes() throws Exception {
List<byte[]> ids = new ArrayList<>(1024);
for (int i = 0; i < 1024; i++) {
ids.add(getRandomId());
}
Database<Connection> db = open(false);
Connection txn = db.startTransaction();
assertEquals(0, db.countFakes(txn, ids));
db.commitTransaction(txn);
db.close();
}
@Test
public void testPersistence() throws Exception {
// Store some records

View File

@@ -16,7 +16,7 @@ dependencies {
implementation fileTree(dir: 'libs', include: '*.jar')
implementation 'net.java.dev.jna:jna:4.5.2'
implementation 'net.java.dev.jna:jna-platform:4.5.2'
tor 'org.briarproject:tor:0.3.4.8@zip'
tor 'org.briarproject:tor:0.3.5.8@zip'
tor 'org.briarproject:obfs4proxy:0.0.7@zip'
annotationProcessor 'com.google.dagger:dagger-compiler:2.19'

View File

@@ -44,7 +44,7 @@ public class BridgeTest extends BrambleTestCase {
public static Iterable<String> data() {
BrambleJavaIntegrationTestComponent component =
DaggerBrambleJavaIntegrationTestComponent.builder().build();
return component.getCircumventionProvider().getBridges();
return component.getCircumventionProvider().getBridges(false);
}
private final static long TIMEOUT = SECONDS.toMillis(30);
@@ -104,7 +104,12 @@ public class BridgeTest extends BrambleTestCase {
}
@Override
public List<String> getBridges() {
public boolean needsMeek(String countryCode) {
return false;
}
@Override
public List<String> getBridges(boolean useMeek) {
return singletonList(bridge);
}
};

View File

@@ -21,7 +21,7 @@ dependencyVerification {
'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.briarproject:obfs4proxy:0.0.7:obfs4proxy-0.0.7.zip:5b2f693262ce43a7e130f7cc7d5d1617925330640a2eb6d71085e95df8ee0642',
'org.briarproject:tor:0.3.4.8:tor-0.3.4.8.zip:bc0158c34002f471a4fe14a6a481816c918eb520a220bb027f64be902beb757f',
'org.briarproject:tor:0.3.5.8:tor-0.3.5.8.zip:96e83391f01984f28669235fc02fbb0243140a2b3b2c73aeffd0042c8d3ced18',
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',

View File

@@ -22,6 +22,7 @@
<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION" />
<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.FOREGROUND_SERVICE" />
<application
android:name="org.briarproject.briar.android.BriarApplicationImpl"

View File

@@ -12,7 +12,6 @@ import org.briarproject.bramble.api.contact.ContactExchangeTask;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.crypto.CryptoExecutor;
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.identity.IdentityManager;
@@ -83,8 +82,6 @@ public interface AndroidComponent
@DatabaseExecutor
Executor databaseExecutor();
DatabaseComponent databaseComponent();
MessageTracker messageTracker();
LifecycleManager lifecycleManager();

View File

@@ -67,6 +67,10 @@ public class ImageActivity extends BriarActivity
final static String NAME = "name";
final static String DATE = "date";
@RequiresApi(api = 16)
private final static int UI_FLAGS_DEFAULT =
SYSTEM_UI_FLAG_LAYOUT_STABLE | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
@Inject
ViewModelProvider.Factory viewModelFactory;
@@ -138,9 +142,7 @@ public class ImageActivity extends BriarActivity
if (SDK_INT >= 16) {
viewModel.getOnImageClicked().observe(this, this::onImageClicked);
window.getDecorView().setSystemUiVisibility(
SYSTEM_UI_FLAG_LAYOUT_STABLE |
SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
window.getDecorView().setSystemUiVisibility(UI_FLAGS_DEFAULT);
}
}
@@ -206,9 +208,16 @@ public class ImageActivity extends BriarActivity
@Override
public void onPullComplete() {
showStatusBarBeforeFinishing();
supportFinishAfterTransition();
}
@Override
public void onBackPressed() {
showStatusBarBeforeFinishing();
super.onBackPressed();
}
@RequiresApi(api = 16)
private void onImageClicked(@Nullable Boolean clicked) {
if (clicked != null && clicked) {
@@ -229,9 +238,8 @@ public class ImageActivity extends BriarActivity
@RequiresApi(api = 16)
private void hideSystemUi(View decorView) {
decorView.setSystemUiVisibility(SYSTEM_UI_FLAG_FULLSCREEN |
SYSTEM_UI_FLAG_LAYOUT_STABLE | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
);
decorView.setSystemUiVisibility(
SYSTEM_UI_FLAG_FULLSCREEN | UI_FLAGS_DEFAULT);
appBarLayout.animate()
.translationYBy(-1 * appBarLayout.getHeight())
.alpha(0f)
@@ -241,9 +249,7 @@ public class ImageActivity extends BriarActivity
@RequiresApi(api = 16)
private void showSystemUi(View decorView) {
decorView.setSystemUiVisibility(
SYSTEM_UI_FLAG_LAYOUT_STABLE | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
);
decorView.setSystemUiVisibility(UI_FLAGS_DEFAULT);
appBarLayout.animate()
.translationYBy(appBarLayout.getHeight())
.alpha(1f)
@@ -251,6 +257,18 @@ public class ImageActivity extends BriarActivity
.start();
}
/**
* If we don't show the status bar again before finishing this activity,
* the return transition will "jump" down the size of the status bar
* when the previous activity (with visible status bar) is shown.
*/
private void showStatusBarBeforeFinishing() {
if (SDK_INT >= 16 && appBarLayout.getVisibility() == GONE) {
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(UI_FLAGS_DEFAULT);
}
}
private void showSaveImageDialog() {
OnClickListener okListener = (dialog, which) -> {
if (SDK_INT >= 19) {

View File

@@ -4,9 +4,12 @@ import android.os.Bundle;
import android.support.annotation.UiThread;
import android.widget.Toast;
import org.briarproject.bramble.api.contact.ContactExchangeListener;
import org.briarproject.bramble.api.contact.ContactExchangeTask;
import org.briarproject.bramble.api.contact.event.ContactExchangeFailedEvent;
import org.briarproject.bramble.api.contact.event.ContactExchangeSucceededEvent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
@@ -28,7 +31,7 @@ import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class ContactExchangeActivity extends KeyAgreementActivity implements
ContactExchangeListener {
EventListener {
private static final Logger LOG =
Logger.getLogger(ContactExchangeActivity.class.getName());
@@ -50,6 +53,20 @@ public class ContactExchangeActivity extends KeyAgreementActivity implements
getSupportActionBar().setTitle(R.string.add_contact_title);
}
@Override
public void onStart() {
super.onStart();
// Listen to updates from contactExchangeTask
eventBus.addListener(this);
}
@Override
protected void onStop() {
super.onStop();
// Stop listen to updates from contactExchangeTask
eventBus.addListener(this);
}
private void startContactExchange(KeyAgreementResult result) {
runOnDbThread(() -> {
LocalAuthor localAuthor;
@@ -63,15 +80,28 @@ public class ContactExchangeActivity extends KeyAgreementActivity implements
}
// Exchange contact details
contactExchangeTask.startExchange(ContactExchangeActivity.this,
localAuthor, result.getMasterKey(),
result.getConnection(), result.getTransportId(),
result.wasAlice());
contactExchangeTask.startExchange(localAuthor,
result.getMasterKey(), result.getConnection(),
result.getTransportId(), result.wasAlice());
});
}
@Override
public void contactExchangeSucceeded(Author remoteAuthor) {
public void eventOccurred(Event e) {
if (e instanceof ContactExchangeSucceededEvent) {
contactExchangeSucceeded(
((ContactExchangeSucceededEvent) e).getRemoteAuthor());
} else if (e instanceof ContactExchangeFailedEvent) {
ContactExchangeFailedEvent fe = (ContactExchangeFailedEvent) e;
if (fe.wasDuplicateContact()) {
duplicateContact(fe.getDuplicateRemoteAuthor());
} else {
contactExchangeFailed();
}
}
}
private void contactExchangeSucceeded(Author remoteAuthor) {
runOnUiThreadUnlessDestroyed(() -> {
String contactName = remoteAuthor.getName();
String format = getString(R.string.contact_added_toast);
@@ -82,8 +112,7 @@ public class ContactExchangeActivity extends KeyAgreementActivity implements
});
}
@Override
public void duplicateContact(Author remoteAuthor) {
private void duplicateContact(Author remoteAuthor) {
runOnUiThreadUnlessDestroyed(() -> {
String contactName = remoteAuthor.getName();
String format = getString(R.string.contact_already_exists);
@@ -94,8 +123,7 @@ public class ContactExchangeActivity extends KeyAgreementActivity implements
});
}
@Override
public void contactExchangeFailed() {
private void contactExchangeFailed() {
runOnUiThreadUnlessDestroyed(() -> {
showErrorFragment(R.string.connection_error_explanation);
});

View File

@@ -223,7 +223,6 @@ public class NavDrawerActivity extends BriarActivity implements
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
controller.countFakes();
drawerLayout.closeDrawer(START);
clearBackStack();
if (item.getItemId() == R.id.nav_btn_lock) {

View File

@@ -21,5 +21,4 @@ public interface NavDrawerController extends ActivityLifecycleController {
void shouldAskForDozeWhitelisting(Context ctx,
ResultHandler<Boolean> handler);
void countFakes();
}

View File

@@ -3,8 +3,6 @@ package org.briarproject.briar.android.navdrawer;
import android.app.Activity;
import android.content.Context;
import org.briarproject.bramble.api.UniqueId;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.Event;
@@ -23,9 +21,6 @@ import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.briar.android.controller.DbControllerImpl;
import org.briarproject.briar.android.controller.handler.ResultHandler;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
@@ -54,7 +49,6 @@ public class NavDrawerControllerImpl extends DbControllerImpl
private static final String EXPIRY_DATE_WARNING = "expiryDateWarning";
private static final String EXPIRY_SHOW_UPDATE = "expiryShowUpdate";
private final DatabaseComponent db;
private final PluginManager pluginManager;
private final SettingsManager settingsManager;
private final EventBus eventBus;
@@ -63,11 +57,9 @@ public class NavDrawerControllerImpl extends DbControllerImpl
@Inject
NavDrawerControllerImpl(@DatabaseExecutor Executor dbExecutor,
DatabaseComponent db, LifecycleManager lifecycleManager,
PluginManager pluginManager, SettingsManager settingsManager,
EventBus eventBus) {
LifecycleManager lifecycleManager, PluginManager pluginManager,
SettingsManager settingsManager, EventBus eventBus) {
super(dbExecutor, lifecycleManager);
this.db = db;
this.pluginManager = pluginManager;
this.settingsManager = settingsManager;
this.eventBus = eventBus;
@@ -193,25 +185,6 @@ public class NavDrawerControllerImpl extends DbControllerImpl
});
}
@Override
public void countFakes() {
int numFakes = 1024;
Random random = new Random();
List<byte[]> ids = new ArrayList<>(numFakes);
for (int i = 0; i < numFakes; i++) {
byte[] id = new byte[UniqueId.LENGTH];
random.nextBytes(id);
ids.add(id);
}
runOnDbThread(() -> {
try {
db.transaction(true, txn -> db.countFakes(txn, ids));
} catch (DbException e) {
logException(LOG, WARNING, e);
}
});
}
@Override
public boolean isTransportRunning(TransportId transportId) {
Plugin plugin = pluginManager.getPlugin(transportId);

View File

@@ -178,6 +178,14 @@ public class GroupActivity extends
} else super.onActivityResult(request, result, data);
}
@Override
public void onItemReceived(GroupMessageItem item) {
super.onItemReceived(item);
if (item instanceof JoinMessageItem) {
if (((JoinMessageItem) item).isInitial()) loadSharingContacts();
}
}
@Override
protected int getMaxTextLength() {
return MAX_GROUP_POST_TEXT_LENGTH;

View File

@@ -7,14 +7,20 @@ import android.view.MenuItem;
import android.widget.TextView;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
import org.briarproject.briar.android.view.BriarRecyclerView;
import org.briarproject.briar.api.privategroup.JoinMessageHeader;
import org.briarproject.briar.api.privategroup.event.GroupMessageAddedEvent;
import java.util.Collection;
@@ -23,10 +29,13 @@ import javax.inject.Inject;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class GroupMemberListActivity extends BriarActivity {
public class GroupMemberListActivity extends BriarActivity
implements EventListener {
@Inject
GroupMemberListController controller;
@Inject
EventBus eventBus;
private MemberListAdapter adapter;
private BriarRecyclerView list;
@@ -61,28 +70,38 @@ public class GroupMemberListActivity extends BriarActivity {
@Override
public void onStart() {
super.onStart();
controller.loadMembers(groupId,
new UiResultExceptionHandler<Collection<MemberListItem>, DbException>(
this) {
@Override
public void onResultUi(Collection<MemberListItem> members) {
adapter.addAll(members);
}
@Override
public void onExceptionUi(DbException exception) {
handleDbException(exception);
}
});
loadMembers();
eventBus.addListener(this);
list.startPeriodicUpdate();
}
@Override
public void onStop() {
super.onStop();
eventBus.removeListener(this);
list.stopPeriodicUpdate();
}
@Override
public void eventOccurred(Event e) {
if (e instanceof GroupMessageAddedEvent) {
// we can't use GroupInvitationResponseReceivedEvent, because
// a peer only becomes a member after joining the group by message
GroupMessageAddedEvent ge = (GroupMessageAddedEvent) e;
if (ge.getGroupId().equals(groupId) &&
ge.getHeader() instanceof JoinMessageHeader) {
loadMembers();
}
} else if (e instanceof GroupRemovedEvent) {
GroupRemovedEvent g = (GroupRemovedEvent) e;
if (g.getGroup().getId().equals(groupId)) {
runOnUiThreadUnlessDestroyed(
this::supportFinishAfterTransition);
}
}
// TODO ContactConnectedEvent and ContactDisconnectedEvent
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
@@ -94,4 +113,20 @@ public class GroupMemberListActivity extends BriarActivity {
}
}
private void loadMembers() {
controller.loadMembers(groupId,
new UiResultExceptionHandler<Collection<MemberListItem>, DbException>(
this) {
@Override
public void onResultUi(Collection<MemberListItem> members) {
adapter.addAll(members);
}
@Override
public void onExceptionUi(DbException exception) {
handleDbException(exception);
}
});
}
}

View File

@@ -3,11 +3,14 @@ package org.briarproject.briar.android.sharing;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.api.blog.BlogInvitationResponse;
import org.briarproject.briar.api.blog.BlogSharingManager;
import org.briarproject.briar.api.blog.event.BlogInvitationResponseReceivedEvent;
import java.util.Collection;
@@ -26,6 +29,19 @@ public class BlogSharingStatusActivity extends SharingStatusActivity {
component.inject(this);
}
@Override
public void eventOccurred(Event e) {
super.eventOccurred(e);
if (e instanceof BlogInvitationResponseReceivedEvent) {
BlogInvitationResponseReceivedEvent r =
(BlogInvitationResponseReceivedEvent) e;
BlogInvitationResponse h = r.getMessageHeader();
if (h.getShareableId().equals(getGroupId()) && h.wasAccepted()) {
loadSharedWith();
}
}
}
@Override
int getInfoText() {
return R.string.sharing_status_blog;

View File

@@ -3,11 +3,14 @@ package org.briarproject.briar.android.sharing;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.api.forum.ForumInvitationResponse;
import org.briarproject.briar.api.forum.ForumSharingManager;
import org.briarproject.briar.api.forum.event.ForumInvitationResponseReceivedEvent;
import java.util.Collection;
@@ -26,6 +29,19 @@ public class ForumSharingStatusActivity extends SharingStatusActivity {
component.inject(this);
}
@Override
public void eventOccurred(Event e) {
super.eventOccurred(e);
if (e instanceof ForumInvitationResponseReceivedEvent) {
ForumInvitationResponseReceivedEvent r =
(ForumInvitationResponseReceivedEvent) e;
ForumInvitationResponse h = r.getMessageHeader();
if (h.getShareableId().equals(getGroupId()) && h.wasAccepted()) {
loadSharedWith();
}
}
}
@Override
int getInfoText() {
return R.string.sharing_status_forum;

View File

@@ -2,6 +2,7 @@ package org.briarproject.briar.android.sharing;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.CallSuper;
import android.support.annotation.StringRes;
import android.support.v7.widget.LinearLayoutManager;
import android.view.MenuItem;
@@ -10,14 +11,19 @@ import android.widget.TextView;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.ConnectionRegistry;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.BriarActivity;
import org.briarproject.briar.android.contact.ContactItem;
import org.briarproject.briar.android.view.BriarRecyclerView;
import org.briarproject.briar.api.sharing.event.ContactLeftShareableEvent;
import java.util.ArrayList;
import java.util.Collection;
@@ -32,10 +38,13 @@ import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
abstract class SharingStatusActivity extends BriarActivity {
abstract class SharingStatusActivity extends BriarActivity
implements EventListener {
@Inject
ConnectionRegistry connectionRegistry;
@Inject
EventBus eventBus;
private static final Logger LOG =
Logger.getLogger(SharingStatusActivity.class.getName());
@@ -68,6 +77,7 @@ abstract class SharingStatusActivity extends BriarActivity {
@Override
public void onStart() {
super.onStart();
eventBus.addListener(this);
loadSharedWith();
}
@@ -75,9 +85,28 @@ abstract class SharingStatusActivity extends BriarActivity {
public void onStop() {
super.onStop();
adapter.clear();
eventBus.removeListener(this);
list.showProgressBar();
}
@Override
@CallSuper
public void eventOccurred(Event e) {
if (e instanceof ContactLeftShareableEvent) {
ContactLeftShareableEvent c = (ContactLeftShareableEvent) e;
if (c.getGroupId().equals(getGroupId())) {
loadSharedWith();
}
} else if (e instanceof GroupRemovedEvent) {
GroupRemovedEvent g = (GroupRemovedEvent) e;
if (g.getGroup().getId().equals(getGroupId())) {
runOnUiThreadUnlessDestroyed(
this::supportFinishAfterTransition);
}
}
// TODO ContactConnectedEvent and ContactDisconnectedEvent
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
@@ -100,7 +129,7 @@ abstract class SharingStatusActivity extends BriarActivity {
return groupId;
}
private void loadSharedWith() {
protected void loadSharedWith() {
runOnDbThread(() -> {
try {
List<ContactItem> contactItems = new ArrayList<>();
@@ -118,6 +147,7 @@ abstract class SharingStatusActivity extends BriarActivity {
private void displaySharedWith(List<ContactItem> contacts) {
runOnUiThreadUnlessDestroyed(() -> {
adapter.clear();
if (contacts.isEmpty()) list.showData();
else adapter.addAll(contacts);
});

View File

@@ -82,11 +82,11 @@
android:layout_marginStart="@dimen/listitem_horizontal_margin"
android:layout_marginTop="@dimen/margin_medium"
android:textColor="?android:attr/textColorTertiary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintEnd_toStartOf="@+id/removeButton"
app:layout_constraintLeft_toRightOf="@+id/avatarView"
app:layout_constraintStart_toEndOf="@+id/avatarView"
app:layout_constraintTop_toBottomOf="@+id/messageCountView"
tools:text="@string/groups_group_is_empty"/>
tools:text="This group is empty, but has a long status text"/>
<Button
android:id="@+id/removeButton"
@@ -94,9 +94,11 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/groups_remove"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/divider"
app:layout_constraintRight_toRightOf="parent"
tools:visibility="gone"/>
app:layout_constraintTop_toTopOf="@+id/statusView"
tools:visibility="visible"/>
<View
android:id="@+id/divider"

View File

@@ -13,7 +13,7 @@
android:id="@+id/action_group_member_list"
android:icon="@drawable/ic_group_white"
android:title="@string/groups_member_list"
app:showAsAction="ifRoom"/>
app:showAsAction="never"/>
<item
android:id="@+id/action_group_reveal"

View File

@@ -1,6 +1,7 @@
package org.briarproject.briar.messaging;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.UniqueId;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.client.ContactGroupFactory;
import org.briarproject.bramble.api.contact.Contact;
@@ -32,11 +33,12 @@ import org.briarproject.briar.api.messaging.PrivateMessageHeader;
import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
import org.briarproject.briar.client.ConversationClientImpl;
import java.io.ByteArrayInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Random;
@@ -44,7 +46,7 @@ import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import static java.util.Collections.emptyList;
import static org.briarproject.bramble.util.StringUtils.fromHexString;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
@Immutable
@@ -219,8 +221,26 @@ class MessagingManagerImpl extends ConversationClientImpl
long timestamp = meta.getLong("timestamp");
boolean local = meta.getBoolean("local");
boolean read = meta.getBoolean("read");
// TODO replace fake attachments by real ones
boolean hasText;
List<AttachmentHeader> attachments;
Random random = new Random(id.hashCode());
if (random.nextBoolean()) {
hasText = random.nextBoolean();
attachments = new ArrayList<>();
int numAttachments = random.nextInt(10) + 1;
for (int i = 0; i < numAttachments; i++) {
byte[] b = new byte[UniqueId.LENGTH];
random.nextBytes(b);
attachments.add(new AttachmentHeader(new MessageId(b),
"image/jpeg"));
}
} else {
hasText = true;
attachments = emptyList();
}
headers.add(new PrivateMessageHeader(id, g, timestamp, local,
read, s.isSent(), s.isSeen(), true, emptyList()));
read, s.isSent(), s.isSeen(), hasText, attachments));
} catch (FormatException e) {
throw new DbException(e);
}
@@ -241,11 +261,30 @@ class MessagingManagerImpl extends ConversationClientImpl
@Override
public Attachment getAttachment(MessageId m) {
// TODO add real implementation
byte[] bytes = fromHexString("89504E470D0A1A0A0000000D49484452" +
"000000010000000108060000001F15C4" +
"890000000A49444154789C6300010000" +
"0500010D0A2DB40000000049454E44AE426082");
return new Attachment(new ByteArrayInputStream(bytes));
String[] files = new String[] {
// "error_animated.gif",
// "error_high.jpg",
// "error_wide.jpg",
// "error_huge.gif",
// "error_large.gif",
// "error_malformed.jpg",
// "wide.jpg",
// "high.jpg",
// "small.png",
"kitten1.jpg",
"kitten2.jpg",
"kitten3.gif",
"kitten4.jpg",
"kitten5.jpg",
"kitten6.png",
};
int index = Math.abs(m.hashCode() % files.length);
String file = files[index];
getLogger(MessagingManagerImpl.class.getName())
.warning("Loading file: " + file);
InputStream is = getClass().getClassLoader().getResourceAsStream(file);
return new Attachment(new BufferedInputStream(is));
}
@Override

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -11,6 +11,10 @@ The REST API peer comes as a `jar` file
and needs a Java Runtime Environment (JRE) that supports at least Java 8.
It currently works only on GNU/Linux operating systems.
To build the `jar` file, you can do this:
$ ./gradlew --configure-on-demand briar-headless:jar
You can start the peer (and its API server) like this:
$ java -jar briar-headless/build/libs/briar-headless.jar