Compare commits

..

3 Commits

Author SHA1 Message Date
Sebastian Kürten
f4f213d80a Add dependency on mailbox from Maven local 2022-08-10 12:05:56 +02:00
akwizgran
fdcacde915 WIP: Integration test for contact list worker 2022-08-02 13:19:04 +01:00
akwizgran
e74021f571 Rename MailboxIntegrationTest, factor out API creation. 2022-08-02 13:17:44 +01:00
105 changed files with 645 additions and 3740 deletions

View File

@@ -15,8 +15,8 @@ android {
defaultConfig {
minSdkVersion 16
targetSdkVersion 30
versionCode 10411
versionName "1.4.11"
versionCode 10410
versionName "1.4.10"
consumerProguardFiles 'proguard-rules.txt'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

View File

@@ -18,7 +18,3 @@
-dontnote com.google.common.**
-dontwarn com.fasterxml.jackson.databind.ext.Java7SupportImpl
# Keep all Jackson-serialisable classes and their members
-keep interface com.fasterxml.jackson.databind.annotation.JsonSerialize
-keep @com.fasterxml.jackson.databind.annotation.JsonSerialize class * { *; }

View File

@@ -1,7 +1,6 @@
package org.briarproject.bramble;
import org.briarproject.bramble.battery.AndroidBatteryModule;
import org.briarproject.bramble.io.DnsModule;
import org.briarproject.bramble.network.AndroidNetworkModule;
import org.briarproject.bramble.plugin.tor.CircumventionModule;
import org.briarproject.bramble.reporting.ReportingModule;
@@ -19,7 +18,6 @@ import dagger.Module;
AndroidTaskSchedulerModule.class,
AndroidWakefulIoExecutorModule.class,
CircumventionModule.class,
DnsModule.class,
ReportingModule.class,
SocksModule.class
})

View File

@@ -5,7 +5,6 @@ targetCompatibility = 1.8
apply plugin: 'ru.vyarus.animalsniffer'
apply plugin: 'witness'
apply from: 'witness.gradle'
apply plugin: 'checkstyle'
dependencies {
implementation "com.google.dagger:dagger:$dagger_version"

View File

@@ -283,13 +283,6 @@ public interface DatabaseComponent extends TransactionManager {
*/
Group getGroup(Transaction txn, GroupId g) throws DbException;
/**
* Returns the ID of the group containing the given message.
* <p/>
* Read-only.
*/
GroupId getGroupId(Transaction txn, MessageId m) throws DbException;
/**
* Returns the metadata for the given group.
* <p/>
@@ -356,13 +349,13 @@ public interface DatabaseComponent extends TransactionManager {
Metadata query) throws DbException;
/**
* Returns the IDs of all messages received from the given contact that
* need to be acknowledged.
* Returns the IDs of some messages received from the given contact that
* need to be acknowledged, up to the given number of messages.
* <p/>
* Read-only.
*/
Collection<MessageId> getMessagesToAck(Transaction txn, ContactId c)
throws DbException;
Collection<MessageId> getMessagesToAck(Transaction txn, ContactId c,
int maxMessages) throws DbException;
/**
* Returns the IDs of some messages that are eligible to be sent to the
@@ -499,8 +492,6 @@ public interface DatabaseComponent extends TransactionManager {
* Returns the message with the given ID for transmission to the given
* contact over a transport with the given maximum latency. Returns null
* if the message is no longer visible to the contact.
* <p/>
* Read-only if {@code markAsSent} is false.
*
* @param markAsSent True if the message should be marked as sent.
* If false it can be marked as sent by calling

View File

@@ -1,22 +1,19 @@
package org.briarproject.bramble.api.mailbox;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.List;
import java.util.TreeSet;
import static org.briarproject.bramble.api.mailbox.MailboxConstants.API_CLIENT_TOO_OLD;
import static org.briarproject.bramble.api.mailbox.MailboxConstants.API_SERVER_TOO_OLD;
@NotNullByDefault
public class MailboxHelper {
class MailboxHelper {
/**
* Returns the highest major version that both client and server support
* or {@link MailboxConstants#API_SERVER_TOO_OLD} if the server is too old
* or {@link MailboxConstants#API_CLIENT_TOO_OLD} if the client is too old.
*/
public static int getHighestCommonMajorVersion(
static int getHighestCommonMajorVersion(
List<MailboxVersion> client, List<MailboxVersion> server) {
TreeSet<Integer> clientVersions = new TreeSet<>();
for (MailboxVersion version : client) {
@@ -35,13 +32,4 @@ public class MailboxHelper {
return API_SERVER_TOO_OLD;
}
/**
* Returns true if a client and server with the given API versions can
* communicate with each other (ie, have any major API versions in common).
*/
public static boolean isClientCompatibleWithServer(
List<MailboxVersion> client, List<MailboxVersion> server) {
int common = getHighestCommonMajorVersion(client, server);
return common != API_CLIENT_TOO_OLD && common != API_SERVER_TOO_OLD;
}
}

View File

@@ -1,7 +1,6 @@
package org.briarproject.bramble.api.mailbox;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.nullsafety.NullSafety;
import java.util.List;
@@ -76,23 +75,4 @@ public class MailboxProperties {
public MailboxFolderId getOutboxId() {
return outboxId;
}
@Override
public boolean equals(Object o) {
if (o instanceof MailboxProperties) {
MailboxProperties m = (MailboxProperties) o;
return owner == m.owner &&
onion.equals(m.onion) &&
authToken.equals(m.authToken) &&
NullSafety.equals(inboxId, m.inboxId) &&
NullSafety.equals(outboxId, m.outboxId) &&
serverSupports.equals(m.serverSupports);
}
return false;
}
@Override
public int hashCode() {
return authToken.hashCode();
}
}

View File

@@ -32,6 +32,9 @@ public interface MailboxSettingsManager {
MailboxStatus getOwnMailboxStatus(Transaction txn) throws DbException;
void recordSuccessfulConnection(Transaction txn, long now)
throws DbException;
void recordSuccessfulConnection(Transaction txn, long now,
List<MailboxVersion> versions) throws DbException;
@@ -46,28 +49,20 @@ public interface MailboxSettingsManager {
interface MailboxHook {
/**
* Called when Briar is paired with a mailbox.
* Called when Briar is paired with a mailbox
*
* @param txn A read-write transaction
* @param ownOnion Our new mailbox's onion (56 base32 chars)
*/
void mailboxPaired(Transaction txn, MailboxProperties p)
void mailboxPaired(Transaction txn, String ownOnion,
List<MailboxVersion> serverSupports)
throws DbException;
/**
* Called when the mailbox is unpaired.
* Called when the mailbox is unpaired
*
* @param txn A read-write transaction
*/
void mailboxUnpaired(Transaction txn) throws DbException;
/**
* Called when we receive our mailbox's server-supported API versions.
* This happens whenever we successfully check the connectivity of
* our mailbox, so this hook may be called frequently.
*
* @param txn A read-write transaction
*/
void serverSupportedVersionsReceived(Transaction txn,
List<MailboxVersion> serverSupports) throws DbException;
}
}

View File

@@ -67,13 +67,6 @@ public class MailboxStatus {
return attemptsSinceSuccess;
}
/**
* Returns the mailbox's supported API versions.
*/
public List<MailboxVersion> getServerSupports() {
return serverSupports;
}
/**
* @return true if this status indicates a problem with the mailbox.
*/

View File

@@ -79,12 +79,6 @@ public interface MailboxUpdateManager {
*/
String GROUP_KEY_SENT_CLIENT_SUPPORTS = "sentClientSupports";
/**
* Key in the client's local group for storing the serverSupports list that
* was last sent out, if any.
*/
String GROUP_KEY_SENT_SERVER_SUPPORTS = "sentServerSupports";
/**
* Returns the latest {@link MailboxUpdate} sent to the given contact.
* <p>

View File

@@ -1,36 +0,0 @@
package org.briarproject.bramble.api.mailbox.event;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.mailbox.MailboxUpdateWithMailbox;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Map;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a mailbox is paired.
*/
@Immutable
@NotNullByDefault
public class MailboxPairedEvent extends Event {
private final MailboxProperties properties;
private final Map<ContactId, MailboxUpdateWithMailbox> localUpdates;
public MailboxPairedEvent(MailboxProperties properties,
Map<ContactId, MailboxUpdateWithMailbox> localUpdates) {
this.properties = properties;
this.localUpdates = localUpdates;
}
public MailboxProperties getProperties() {
return properties;
}
public Map<ContactId, MailboxUpdateWithMailbox> getLocalUpdates() {
return localUpdates;
}
}

View File

@@ -1,28 +0,0 @@
package org.briarproject.bramble.api.mailbox.event;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.mailbox.MailboxUpdate;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Map;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a mailbox is unpaired.
*/
@Immutable
@NotNullByDefault
public class MailboxUnpairedEvent extends Event {
private final Map<ContactId, MailboxUpdate> localUpdates;
public MailboxUnpairedEvent(Map<ContactId, MailboxUpdate> localUpdates) {
this.localUpdates = localUpdates;
}
public Map<ContactId, MailboxUpdate> getLocalUpdates() {
return localUpdates;
}
}

View File

@@ -1,40 +0,0 @@
package org.briarproject.bramble.api.mailbox.event;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.mailbox.MailboxUpdate;
import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when the first mailbox update is sent to a
* newly added contact, which happens in the same transaction in which the
* contact is added.
* <p>
* This event is not broadcast when the first mailbox update is sent to an
* existing contact when setting up the
* {@link MailboxUpdateManager mailbox update client}.
*/
@Immutable
@NotNullByDefault
public class MailboxUpdateSentToNewContactEvent extends Event {
private final ContactId contactId;
private final MailboxUpdate mailboxUpdate;
public MailboxUpdateSentToNewContactEvent(ContactId contactId,
MailboxUpdate mailboxUpdate) {
this.contactId = contactId;
this.mailboxUpdate = mailboxUpdate;
}
public ContactId getContactId() {
return contactId;
}
public MailboxUpdate getMailboxUpdate() {
return mailboxUpdate;
}
}

View File

@@ -1,14 +1,9 @@
package org.briarproject.bramble.api.sync.event;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Group.Visibility;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId;
import java.util.Map;
import javax.annotation.concurrent.Immutable;
/**
@@ -19,32 +14,12 @@ import javax.annotation.concurrent.Immutable;
public class MessageSharedEvent extends Event {
private final MessageId messageId;
private final GroupId groupId;
private final Map<ContactId, Boolean> groupVisibility;
public MessageSharedEvent(MessageId message, GroupId groupId,
Map<ContactId, Boolean> groupVisibility) {
public MessageSharedEvent(MessageId message) {
this.messageId = message;
this.groupId = groupId;
this.groupVisibility = groupVisibility;
}
public MessageId getMessageId() {
return messageId;
}
public GroupId getGroupId() {
return groupId;
}
/**
* Returns the IDs of all contacts for which the visibility of the
* message's group is either {@link Visibility#SHARED shared} or
* {@link Visibility#VISIBLE visible}. The value in the map is true if the
* group is {@link Visibility#SHARED shared} or false if the group is
* {@link Visibility#VISIBLE visible}.
*/
public Map<ContactId, Boolean> getGroupVisibility() {
return groupVisibility;
}
}

View File

@@ -338,17 +338,6 @@ public class TestUtils {
return false;
}
public static <E extends Event> E getEvent(Transaction txn,
Class<E> eventClass) {
for (CommitAction action : txn.getActions()) {
if (action instanceof EventAction) {
Event event = ((EventAction) action).getEvent();
if (eventClass.isInstance(event)) return eventClass.cast(event);
}
}
throw new AssertionError();
}
public static boolean isCryptoStrengthUnlimited() {
try {
return Cipher.getMaxAllowedKeyLength("AES/CBC/PKCS5Padding")

View File

@@ -7,7 +7,6 @@ apply plugin: 'idea'
apply plugin: 'witness'
apply from: 'witness.gradle'
apply from: '../dagger.gradle'
apply plugin: 'checkstyle'
dependencies {
implementation project(path: ':bramble-api', configuration: 'default')
@@ -33,6 +32,7 @@ dependencies {
testImplementation "org.jmock:jmock-junit4:$jmock_version"
testImplementation "org.jmock:jmock-imposters:$jmock_version"
testImplementation "com.squareup.okhttp3:mockwebserver:4.9.3"
testImplementation "org.briarproject:mailbox-lib:0.1"
testAnnotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"

View File

@@ -52,7 +52,6 @@ import java.util.Map.Entry;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import static java.util.Collections.sort;
import static org.briarproject.bramble.api.client.ContactGroupConstants.GROUP_KEY_CONTACT_ID;
import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
@@ -475,8 +474,6 @@ class ClientHelperImpl implements ClientHelper {
list.add(new MailboxVersion(element.getLong(0).intValue(),
element.getLong(1).intValue()));
}
// Sort the list of versions for easier comparison
sort(list);
return list;
}

View File

@@ -320,13 +320,6 @@ interface Database<T> {
*/
Group getGroup(T txn, GroupId g) throws DbException;
/**
* Returns the ID of the group containing the given message.
* <p/>
* Read-only.
*/
GroupId getGroupId(T txn, MessageId m) throws DbException;
/**
* Returns the metadata for the given group.
* <p/>
@@ -352,11 +345,8 @@ interface Database<T> {
throws DbException;
/**
* Returns the IDs of all contacts for which the given group's visibility
* is either {@link Visibility#SHARED shared} or
* {@link Visibility#VISIBLE visible}. The value in the map is true if the
* group is {@link Visibility#SHARED shared} or false if the group is
* {@link Visibility#VISIBLE visible}.
* Returns the IDs of all contacts to which the given group's visibility is
* either {@link Visibility VISIBLE} or {@link Visibility SHARED}.
* <p/>
* Read-only.
*/

View File

@@ -287,12 +287,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
transaction.attach(new MessageAddedEvent(m, null));
transaction.attach(new MessageStateChangedEvent(m.getId(), true,
DELIVERED));
if (shared) {
Map<ContactId, Boolean> visibility =
db.getGroupVisibility(txn, m.getGroupId());
transaction.attach(new MessageSharedEvent(m.getId(),
m.getGroupId(), visibility));
}
if (shared) transaction.attach(new MessageSharedEvent(m.getId()));
}
db.mergeMessageMetadata(txn, m.getId(), meta);
}
@@ -555,15 +550,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
return db.getGroup(txn, g);
}
@Override
public GroupId getGroupId(Transaction transaction, MessageId m)
throws DbException {
T txn = unbox(transaction);
if (!db.containsMessage(txn, m))
throw new NoSuchMessageException();
return db.getGroupId(txn, m);
}
@Override
public Metadata getGroupMetadata(Transaction transaction, GroupId g)
throws DbException {
@@ -634,11 +620,11 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
@Override
public Collection<MessageId> getMessagesToAck(Transaction transaction,
ContactId c) throws DbException {
ContactId c, int maxMessages) throws DbException {
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
return db.getMessagesToAck(txn, c, Integer.MAX_VALUE);
return db.getMessagesToAck(txn, c, maxMessages);
}
@Override
@@ -760,9 +746,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
public Message getMessageToSend(Transaction transaction, ContactId c,
MessageId m, long maxLatency, boolean markAsSent)
throws DbException {
if (markAsSent && transaction.isReadOnly()) {
throw new IllegalArgumentException();
}
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
@@ -1113,7 +1097,11 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
db.lowerAckFlag(txn, c, acked);
List<MessageId> visible = new ArrayList<>(acked.size());
for (MessageId m : acked) {
if (db.containsVisibleMessage(txn, c, m)) visible.add(m);
}
db.lowerAckFlag(txn, c, visible);
}
@Override
@@ -1196,9 +1184,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
if (db.getMessageState(txn, m) != DELIVERED)
throw new IllegalArgumentException("Shared undelivered message");
db.setMessageShared(txn, m, true);
GroupId g = db.getGroupId(txn, m);
Map<ContactId, Boolean> visibility = db.getGroupVisibility(txn, g);
transaction.attach(new MessageSharedEvent(m, g, visibility));
transaction.attach(new MessageSharedEvent(m));
}
@Override

View File

@@ -1683,27 +1683,6 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
@Override
public GroupId getGroupId(Connection txn, MessageId m) throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT groupId FROM messages WHERE messageId = ?";
ps = txn.prepareStatement(sql);
ps.setBytes(1, m.getBytes());
rs = ps.executeQuery();
if (!rs.next()) throw new DbStateException();
GroupId g = new GroupId(rs.getBytes(1));
rs.close();
ps.close();
return g;
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@Override
public Collection<Group> getGroups(Connection txn, ClientId c,
int majorVersion) throws DbException {

View File

@@ -55,10 +55,6 @@ class ContactMailboxClient implements MailboxClient {
}
if (uploadWorker != null) uploadWorker.destroy();
if (downloadWorker != null) downloadWorker.destroy();
// The connectivity checker belongs to the client, so it should be
// destroyed. The Tor reachability monitor is shared between clients,
// so it should not be destroyed
connectivityChecker.destroy();
}
@Override

View File

@@ -5,23 +5,14 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.mailbox.MailboxApi.ApiException;
import java.util.logging.Logger;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static java.util.logging.Logger.getLogger;
@ThreadSafe
@NotNullByDefault
class ContactMailboxConnectivityChecker extends ConnectivityCheckerImpl {
private static final Logger LOG =
getLogger(ContactMailboxConnectivityChecker.class.getName());
private final MailboxApi mailboxApi;
@Inject
ContactMailboxConnectivityChecker(Clock clock,
MailboxApiCaller mailboxApiCaller, MailboxApi mailboxApi) {
super(clock, mailboxApiCaller);
@@ -32,9 +23,7 @@ class ContactMailboxConnectivityChecker extends ConnectivityCheckerImpl {
ApiCall createConnectivityCheckTask(MailboxProperties properties) {
if (properties.isOwner()) throw new IllegalArgumentException();
return new SimpleApiCall(() -> {
LOG.info("Checking connectivity of contact's mailbox");
if (!mailboxApi.checkStatus(properties)) throw new ApiException();
LOG.info("Contact's mailbox is reachable");
// Call the observers and cache the result
onConnectivityCheckSucceeded(clock.currentTimeMillis());
});

View File

@@ -22,6 +22,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.inject.Inject;
@@ -34,7 +35,6 @@ import okhttp3.Response;
import okhttp3.ResponseBody;
import static com.fasterxml.jackson.databind.MapperFeature.BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES;
import static java.util.Collections.sort;
import static java.util.Objects.requireNonNull;
import static okhttp3.internal.Util.EMPTY_REQUEST;
import static org.briarproject.bramble.util.IoUtils.copyAndClose;
@@ -125,8 +125,6 @@ class MailboxApiImpl implements MailboxApi {
if (major < 0 || minor < 0) throw new ApiException();
serverSupports.add(new MailboxVersion(major, minor));
}
// Sort the list of versions for easier comparison
sort(serverSupports);
return serverSupports;
}
@@ -247,7 +245,7 @@ class MailboxApiImpl implements MailboxApi {
if (time < 1) throw new ApiException();
list.add(new MailboxFile(MailboxFileId.fromString(name), time));
}
sort(list);
Collections.sort(list);
return list;
} catch (JacksonException | InvalidMailboxIdException e) {
throw new ApiException();

View File

@@ -1,21 +0,0 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
interface MailboxClientFactory {
/**
* Creates a client for communicating with a contact's mailbox.
*/
MailboxClient createContactMailboxClient(
TorReachabilityMonitor reachabilityMonitor);
/**
* Creates a client for communicating with our own mailbox.
*/
MailboxClient createOwnMailboxClient(
TorReachabilityMonitor reachabilityMonitor,
MailboxProperties properties);
}

View File

@@ -1,52 +0,0 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.TaskScheduler;
import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Provider;
@NotNullByDefault
class MailboxClientFactoryImpl implements MailboxClientFactory {
private final MailboxWorkerFactory workerFactory;
private final TaskScheduler taskScheduler;
private final Executor ioExecutor;
private final Provider<ContactMailboxConnectivityChecker>
contactCheckerProvider;
private final Provider<OwnMailboxConnectivityChecker> ownCheckerProvider;
@Inject
MailboxClientFactoryImpl(MailboxWorkerFactory workerFactory,
TaskScheduler taskScheduler,
@IoExecutor Executor ioExecutor,
Provider<ContactMailboxConnectivityChecker> contactCheckerProvider,
Provider<OwnMailboxConnectivityChecker> ownCheckerProvider) {
this.workerFactory = workerFactory;
this.taskScheduler = taskScheduler;
this.ioExecutor = ioExecutor;
this.contactCheckerProvider = contactCheckerProvider;
this.ownCheckerProvider = ownCheckerProvider;
}
@Override
public MailboxClient createContactMailboxClient(
TorReachabilityMonitor reachabilityMonitor) {
ConnectivityChecker connectivityChecker = contactCheckerProvider.get();
return new ContactMailboxClient(workerFactory, connectivityChecker,
reachabilityMonitor);
}
@Override
public MailboxClient createOwnMailboxClient(
TorReachabilityMonitor reachabilityMonitor,
MailboxProperties properties) {
ConnectivityChecker connectivityChecker = ownCheckerProvider.get();
return new OwnMailboxClient(workerFactory, connectivityChecker,
reachabilityMonitor, taskScheduler, ioExecutor, properties);
}
}

View File

@@ -1,667 +0,0 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.TransactionManager;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventExecutor;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.lifecycle.ServiceException;
import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import org.briarproject.bramble.api.mailbox.MailboxStatus;
import org.briarproject.bramble.api.mailbox.MailboxUpdate;
import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
import org.briarproject.bramble.api.mailbox.MailboxUpdateWithMailbox;
import org.briarproject.bramble.api.mailbox.MailboxVersion;
import org.briarproject.bramble.api.mailbox.event.MailboxPairedEvent;
import org.briarproject.bramble.api.mailbox.event.MailboxUnpairedEvent;
import org.briarproject.bramble.api.mailbox.event.MailboxUpdateSentToNewContactEvent;
import org.briarproject.bramble.api.mailbox.event.OwnMailboxConnectionStatusEvent;
import org.briarproject.bramble.api.mailbox.event.RemoteMailboxUpdateEvent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Plugin;
import org.briarproject.bramble.api.plugin.PluginManager;
import org.briarproject.bramble.api.plugin.event.TransportActiveEvent;
import org.briarproject.bramble.api.plugin.event.TransportInactiveEvent;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.mailbox.MailboxConstants.CLIENT_SUPPORTS;
import static org.briarproject.bramble.api.mailbox.MailboxHelper.isClientCompatibleWithServer;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
import static org.briarproject.bramble.api.plugin.TorConstants.ID;
import static org.briarproject.bramble.util.LogUtils.logException;
/**
* This component manages a {@link MailboxClient} for each mailbox we know
* about and are able to use (our own mailbox and/or contacts' mailboxes).
* The clients are created when we come online (i.e. when the Tor plugin
* becomes {@link Plugin.State#ACTIVE active}) and destroyed when we go
* offline.
* <p/>
* The manager keeps track of the latest {@link MailboxUpdate} sent to and
* received from each contact. These updates are used to decide which
* mailboxes the manager needs clients for, and which mailbox (if any) should
* be used for uploading data to and/or downloading data from each contact.
* <p/>
* The assignments of contacts to mailboxes for upload and/or download may
* change when the following events happen:
* <ul>
* <li> A mailbox is paired or unpaired </li>
* <li> A contact is added or removed </li>
* <li> A {@link MailboxUpdate} is received from a contact </li>
* <li> We discover that our own mailbox's supported API versions have
* changed </li>
* </ul>
* <p/>
* The manager keeps its mutable state consistent with the state in the DB by
* using commit actions and events to update the manager's state on the event
* thread.
*/
@ThreadSafe
@NotNullByDefault
class MailboxClientManager implements Service, EventListener {
private static final Logger LOG =
getLogger(MailboxClientManager.class.getName());
private final Executor eventExecutor, dbExecutor;
private final TransactionManager db;
private final ContactManager contactManager;
private final PluginManager pluginManager;
private final MailboxSettingsManager mailboxSettingsManager;
private final MailboxUpdateManager mailboxUpdateManager;
private final MailboxClientFactory mailboxClientFactory;
private final TorReachabilityMonitor reachabilityMonitor;
private final AtomicBoolean used = new AtomicBoolean(false);
// All of the following mutable state must only be accessed on the
// event thread
private final Map<ContactId, Updates> contactUpdates = new HashMap<>();
private final Map<ContactId, MailboxClient> contactClients =
new HashMap<>();
@Nullable
private MailboxProperties ownProperties = null;
@Nullable
private MailboxClient ownClient = null;
private boolean online = false, handleEvents = false;
@Inject
MailboxClientManager(@EventExecutor Executor eventExecutor,
@DatabaseExecutor Executor dbExecutor,
TransactionManager db,
ContactManager contactManager,
PluginManager pluginManager,
MailboxSettingsManager mailboxSettingsManager,
MailboxUpdateManager mailboxUpdateManager,
MailboxClientFactory mailboxClientFactory,
TorReachabilityMonitor reachabilityMonitor) {
this.eventExecutor = eventExecutor;
this.dbExecutor = dbExecutor;
this.db = db;
this.contactManager = contactManager;
this.pluginManager = pluginManager;
this.mailboxSettingsManager = mailboxSettingsManager;
this.mailboxUpdateManager = mailboxUpdateManager;
this.mailboxClientFactory = mailboxClientFactory;
this.reachabilityMonitor = reachabilityMonitor;
}
@Override
public void startService() throws ServiceException {
if (used.getAndSet(true)) throw new IllegalStateException();
reachabilityMonitor.start();
dbExecutor.execute(this::loadMailboxProperties);
}
@DatabaseExecutor
private void loadMailboxProperties() {
LOG.info("Loading mailbox properties");
try {
db.transaction(true, txn -> {
Map<ContactId, Updates> updates = new HashMap<>();
for (Contact c : contactManager.getContacts(txn)) {
MailboxUpdate local = mailboxUpdateManager
.getLocalUpdate(txn, c.getId());
MailboxUpdate remote = mailboxUpdateManager
.getRemoteUpdate(txn, c.getId());
updates.put(c.getId(), new Updates(local, remote));
}
MailboxProperties ownProps =
mailboxSettingsManager.getOwnMailboxProperties(txn);
// Use a commit action so the state in memory remains
// consistent with the state in the DB
txn.attach(() -> initialiseState(updates, ownProps));
});
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}
@EventExecutor
private void initialiseState(Map<ContactId, Updates> updates,
@Nullable MailboxProperties ownProps) {
contactUpdates.putAll(updates);
ownProperties = ownProps;
Plugin tor = pluginManager.getPlugin(ID);
if (tor != null && tor.getState() == ACTIVE) {
LOG.info("Online");
online = true;
createClients();
}
// Now that the mutable state has been initialised we can start
// handling events. This is done in a commit action so that we don't
// miss any changes to the DB state or handle events for any changes
// that were already reflected in the initial load
handleEvents = true;
}
@EventExecutor
private void createClients() {
LOG.info("Creating clients");
for (Entry<ContactId, Updates> e : contactUpdates.entrySet()) {
ContactId c = e.getKey();
Updates u = e.getValue();
if (isContactMailboxUsable(u.remote)) {
// Create and start a client for the contact's mailbox
MailboxClient contactClient = createAndStartClient(c);
// Assign the contact to the contact's mailbox for upload
assignContactToContactMailboxForUpload(c, contactClient, u);
if (!isOwnMailboxUsable(ownProperties, u.remote)) {
// We don't have a usable mailbox, so assign the contact to
// the contact's mailbox for download too
assignContactToContactMailboxForDownload(c,
contactClient, u);
}
}
}
if (ownProperties == null) return;
if (!isOwnMailboxUsable(ownProperties)) {
LOG.warning("We have a mailbox but we can't use it");
return;
}
// Create and start a client for our mailbox
createAndStartClientForOwnMailbox();
// Assign contacts to our mailbox for upload/download
for (Entry<ContactId, Updates> e : contactUpdates.entrySet()) {
ContactId c = e.getKey();
Updates u = e.getValue();
if (isOwnMailboxUsable(ownProperties, u.remote)) {
// Assign the contact to our mailbox for download
assignContactToOwnMailboxForDownload(c, u);
if (!isContactMailboxUsable(u.remote)) {
// The contact doesn't have a usable mailbox, so assign
// the contact to our mailbox for upload too
assignContactToOwnMailboxForUpload(c, u);
}
}
}
}
@Override
public void stopService() throws ServiceException {
CountDownLatch latch = new CountDownLatch(1);
eventExecutor.execute(() -> {
handleEvents = false;
if (online) destroyClients();
latch.countDown();
});
reachabilityMonitor.destroy();
try {
latch.await();
} catch (InterruptedException e) {
throw new ServiceException(e);
}
}
@EventExecutor
private void destroyClients() {
LOG.info("Destroying clients");
for (MailboxClient client : contactClients.values()) {
client.destroy();
}
contactClients.clear();
destroyOwnClient();
}
@EventExecutor
private void destroyOwnClient() {
if (ownClient != null) {
ownClient.destroy();
ownClient = null;
}
}
@Override
public void eventOccurred(Event e) {
if (!handleEvents) return;
if (e instanceof TransportActiveEvent) {
TransportActiveEvent t = (TransportActiveEvent) e;
if (t.getTransportId().equals(ID)) onTorActive();
} else if (e instanceof TransportInactiveEvent) {
TransportInactiveEvent t = (TransportInactiveEvent) e;
if (t.getTransportId().equals(ID)) onTorInactive();
} else if (e instanceof MailboxPairedEvent) {
LOG.info("Mailbox paired");
MailboxPairedEvent m = (MailboxPairedEvent) e;
onMailboxPaired(m.getProperties(), m.getLocalUpdates());
} else if (e instanceof MailboxUnpairedEvent) {
LOG.info("Mailbox unpaired");
MailboxUnpairedEvent m = (MailboxUnpairedEvent) e;
onMailboxUnpaired(m.getLocalUpdates());
} else if (e instanceof MailboxUpdateSentToNewContactEvent) {
LOG.info("Contact added");
MailboxUpdateSentToNewContactEvent
m = (MailboxUpdateSentToNewContactEvent) e;
onContactAdded(m.getContactId(), m.getMailboxUpdate());
} else if (e instanceof ContactRemovedEvent) {
LOG.info("Contact removed");
ContactRemovedEvent c = (ContactRemovedEvent) e;
onContactRemoved(c.getContactId());
} else if (e instanceof RemoteMailboxUpdateEvent) {
LOG.info("Remote mailbox update");
RemoteMailboxUpdateEvent r = (RemoteMailboxUpdateEvent) e;
onRemoteMailboxUpdate(r.getContact(), r.getMailboxUpdate());
} else if (e instanceof OwnMailboxConnectionStatusEvent) {
OwnMailboxConnectionStatusEvent o =
(OwnMailboxConnectionStatusEvent) e;
onOwnMailboxConnectionStatusChanged(o.getStatus());
}
}
@EventExecutor
private void onTorActive() {
// If we checked the plugin at startup concurrently with the plugin
// becoming active then `online` may already be true when we receive
// the first TransportActiveEvent, in which case ignore it
if (online) return;
LOG.info("Online");
online = true;
createClients();
}
@EventExecutor
private void onTorInactive() {
// If we checked the plugin at startup concurrently with the plugin
// becoming inactive then `online` may already be false when we
// receive the first TransportInactiveEvent, in which case ignore it
if (!online) return;
LOG.info("Offline");
online = false;
destroyClients();
}
@EventExecutor
private void onMailboxPaired(MailboxProperties ownProps,
Map<ContactId, MailboxUpdateWithMailbox> localUpdates) {
for (Entry<ContactId, MailboxUpdateWithMailbox> e :
localUpdates.entrySet()) {
ContactId c = e.getKey();
Updates u = contactUpdates.get(c);
contactUpdates.put(c, new Updates(e.getValue(), u.remote));
}
ownProperties = ownProps;
if (!online) return;
if (!isOwnMailboxUsable(ownProperties)) {
LOG.warning("We have a mailbox but we can't use it");
return;
}
// Create and start a client for our mailbox
createAndStartClientForOwnMailbox();
// Assign contacts to our mailbox for upload/download
for (Entry<ContactId, Updates> e : contactUpdates.entrySet()) {
ContactId c = e.getKey();
Updates u = e.getValue();
if (!isOwnMailboxUsable(ownProperties, u.remote)) {
// Our mailbox isn't usable for communicating with this
// contact, so don't assign/reassign this contact
continue;
}
if (isContactMailboxUsable(u.remote)) {
// The contact has a usable mailbox, so the contact should
// currently be assigned to the contact's mailbox for upload
// and download. Reassign the contact to our mailbox for
// download
MailboxClient contactClient =
requireNonNull(contactClients.get(c));
contactClient.deassignContactForDownload(c);
} else {
// The contact doesn't have a usable mailbox, so assign the
// contact to our mailbox for upload
assignContactToOwnMailboxForUpload(c, u);
}
assignContactToOwnMailboxForDownload(c, u);
}
}
@EventExecutor
private void onMailboxUnpaired(Map<ContactId, MailboxUpdate> localUpdates) {
for (Entry<ContactId, MailboxUpdate> e : localUpdates.entrySet()) {
ContactId c = e.getKey();
Updates updates = contactUpdates.get(c);
contactUpdates.put(c, new Updates(e.getValue(), updates.remote));
}
MailboxProperties oldOwnProperties = ownProperties;
ownProperties = null;
if (!online) return;
// Destroy the client for our own mailbox, if any
destroyOwnClient();
// Reassign contacts to their own mailboxes for download where possible
for (Entry<ContactId, Updates> e : contactUpdates.entrySet()) {
ContactId c = e.getKey();
Updates u = e.getValue();
if (isContactMailboxUsable(u.remote) &&
isOwnMailboxUsable(oldOwnProperties, u.remote)) {
// The contact should currently be assigned to our mailbox
// for download. Reassign the contact to the contact's
// mailbox for download
MailboxClient contactClient =
requireNonNull(contactClients.get(c));
assignContactToContactMailboxForDownload(c, contactClient, u);
}
}
}
@EventExecutor
private void onContactAdded(ContactId c, MailboxUpdate u) {
Updates old = contactUpdates.put(c, new Updates(u, null));
if (old != null) throw new IllegalStateException();
// We haven't yet received an update from the newly added contact,
// so at this stage we don't need to assign the contact to any
// mailboxes for upload or download
}
@EventExecutor
private void onContactRemoved(ContactId c) {
Updates updates = requireNonNull(contactUpdates.remove(c));
if (!online) return;
// Destroy the client for the contact's mailbox, if any
MailboxClient client = contactClients.remove(c);
if (client != null) client.destroy();
// If we have a mailbox and the contact is assigned to it for upload
// and/or download, deassign the contact
if (ownProperties == null) return;
if (isOwnMailboxUsable(ownProperties, updates.remote)) {
// We have a usable mailbox, so the contact should currently be
// assigned to our mailbox for download. Deassign the contact from
// our mailbox for download
requireNonNull(ownClient).deassignContactForDownload(c);
if (!isContactMailboxUsable(updates.remote)) {
// The contact doesn't have a usable mailbox, so the contact
// should currently be assigned to our mailbox for upload.
// Deassign the contact from our mailbox for upload
requireNonNull(ownClient).deassignContactForUpload(c);
}
}
}
@EventExecutor
private void onRemoteMailboxUpdate(ContactId c, MailboxUpdate remote) {
Updates old = contactUpdates.get(c);
MailboxUpdate oldRemote = old.remote;
Updates u = new Updates(old.local, remote);
contactUpdates.put(c, u);
if (!online) return;
// What may have changed?
// * Contact's mailbox may be usable now, was unusable before
// * Contact's mailbox may be unusable now, was usable before
// * Contact's mailbox may have been replaced
// * Contact's mailbox may have changed its API versions
// * Contact may be able to use our mailbox now, was unable before
// * Contact may be unable to use our mailbox now, was able before
boolean wasContactMailboxUsable = isContactMailboxUsable(oldRemote);
boolean isContactMailboxUsable = isContactMailboxUsable(remote);
boolean wasOwnMailboxUsable =
isOwnMailboxUsable(ownProperties, oldRemote);
boolean isOwnMailboxUsable = isOwnMailboxUsable(ownProperties, remote);
// Create/destroy/replace the client for the contact's mailbox if needed
MailboxClient contactClient = null;
boolean clientReplaced = false;
if (isContactMailboxUsable) {
if (wasContactMailboxUsable) {
MailboxProperties oldProps = getMailboxProperties(oldRemote);
MailboxProperties newProps = getMailboxProperties(remote);
if (oldProps.equals(newProps)) {
// The contact previously had a usable mailbox, now has
// a usable mailbox, it's the same mailbox, and its API
// versions haven't changed. Keep using the existing client
contactClient = requireNonNull(contactClients.get(c));
} else {
// The contact previously had a usable mailbox and now has
// a usable mailbox, but either it's a new mailbox or its
// API versions have changed. Replace the client
requireNonNull(contactClients.remove(c)).destroy();
contactClient = createAndStartClient(c);
clientReplaced = true;
}
} else {
// The client didn't previously have a usable mailbox but now
// has one. Create and start a client
contactClient = createAndStartClient(c);
}
} else if (wasContactMailboxUsable) {
// The client previously had a usable mailbox but no longer does.
// Destroy the existing client
requireNonNull(contactClients.remove(c)).destroy();
}
boolean wasAssignedToOwnMailboxForUpload =
wasOwnMailboxUsable && !wasContactMailboxUsable;
boolean willBeAssignedToOwnMailboxForUpload =
isOwnMailboxUsable && !isContactMailboxUsable;
boolean wasAssignedToContactMailboxForDownload =
!wasOwnMailboxUsable && wasContactMailboxUsable;
boolean willBeAssignedToContactMailboxForDownload =
!isOwnMailboxUsable && isContactMailboxUsable;
// Deassign the contact for upload/download if needed
if (wasAssignedToOwnMailboxForUpload &&
!willBeAssignedToOwnMailboxForUpload) {
requireNonNull(ownClient).deassignContactForUpload(c);
}
if (wasOwnMailboxUsable && !isOwnMailboxUsable) {
requireNonNull(ownClient).deassignContactForDownload(c);
}
// If the client for the contact's mailbox was replaced or destroyed
// above then we don't need to deassign the contact for download
if (wasAssignedToContactMailboxForDownload &&
!willBeAssignedToContactMailboxForDownload &&
!clientReplaced && isContactMailboxUsable) {
requireNonNull(contactClient).deassignContactForDownload(c);
}
// We never need to deassign the contact from the contact's mailbox for
// upload: this would only be needed if the contact's mailbox were no
// longer usable, in which case the client would already have been
// destroyed above. Thanks to the linter for spotting this
// Assign the contact for upload/download if needed
if (!wasAssignedToOwnMailboxForUpload &&
willBeAssignedToOwnMailboxForUpload) {
assignContactToOwnMailboxForUpload(c, u);
}
if (!wasOwnMailboxUsable && isOwnMailboxUsable) {
assignContactToOwnMailboxForDownload(c, u);
}
if ((!wasContactMailboxUsable || clientReplaced) &&
isContactMailboxUsable) {
assignContactToContactMailboxForUpload(c, contactClient, u);
}
if ((!wasAssignedToContactMailboxForDownload || clientReplaced) &&
willBeAssignedToContactMailboxForDownload) {
assignContactToContactMailboxForDownload(c, contactClient, u);
}
}
@EventExecutor
private void onOwnMailboxConnectionStatusChanged(MailboxStatus status) {
if (!online || ownProperties == null) return;
List<MailboxVersion> oldServerSupports =
ownProperties.getServerSupports();
List<MailboxVersion> newServerSupports = status.getServerSupports();
if (!oldServerSupports.equals(newServerSupports)) {
LOG.info("Our mailbox's supported API versions have changed");
// This potentially affects every assignment of contacts to
// mailboxes for upload and download, so just rebuild the clients
// and assignments from scratch
destroyClients();
createClients();
}
}
@EventExecutor
private void createAndStartClientForOwnMailbox() {
if (ownClient != null) throw new IllegalStateException();
ownClient = mailboxClientFactory.createOwnMailboxClient(
reachabilityMonitor, requireNonNull(ownProperties));
ownClient.start();
}
@EventExecutor
private MailboxClient createAndStartClient(ContactId c) {
MailboxClient client = mailboxClientFactory
.createContactMailboxClient(reachabilityMonitor);
MailboxClient old = contactClients.put(c, client);
if (old != null) throw new IllegalStateException();
client.start();
return client;
}
@EventExecutor
private void assignContactToOwnMailboxForDownload(ContactId c, Updates u) {
MailboxProperties localProps = getMailboxProperties(u.local);
requireNonNull(ownClient).assignContactForDownload(c,
requireNonNull(ownProperties),
requireNonNull(localProps.getOutboxId()));
}
@EventExecutor
private void assignContactToOwnMailboxForUpload(ContactId c, Updates u) {
MailboxProperties localProps = getMailboxProperties(u.local);
requireNonNull(ownClient).assignContactForUpload(c,
requireNonNull(ownProperties),
requireNonNull(localProps.getInboxId()));
}
@EventExecutor
private void assignContactToContactMailboxForDownload(ContactId c,
MailboxClient contactClient, Updates u) {
MailboxProperties remoteProps =
getMailboxProperties(requireNonNull(u.remote));
contactClient.assignContactForDownload(c, remoteProps,
requireNonNull(remoteProps.getInboxId()));
}
@EventExecutor
private void assignContactToContactMailboxForUpload(ContactId c,
MailboxClient contactClient, Updates u) {
MailboxProperties remoteProps =
getMailboxProperties(requireNonNull(u.remote));
contactClient.assignContactForUpload(c, remoteProps,
requireNonNull(remoteProps.getOutboxId()));
}
/**
* Returns the {@link MailboxProperties} included in the given update,
* which must be a {@link MailboxUpdateWithMailbox}.
*/
private MailboxProperties getMailboxProperties(MailboxUpdate update) {
if (!(update instanceof MailboxUpdateWithMailbox)) {
throw new IllegalArgumentException();
}
MailboxUpdateWithMailbox mailbox = (MailboxUpdateWithMailbox) update;
return mailbox.getMailboxProperties();
}
/**
* Returns true if we can use our own mailbox to communicate with the
* contact that sent the given update.
*/
private boolean isOwnMailboxUsable(
@Nullable MailboxProperties ownProperties,
@Nullable MailboxUpdate remote) {
if (ownProperties == null || remote == null) return false;
return isMailboxUsable(remote.getClientSupports(),
ownProperties.getServerSupports());
}
/**
* Returns true if we can use the contact's mailbox to communicate with
* the contact that sent the given update.
*/
private boolean isContactMailboxUsable(@Nullable MailboxUpdate remote) {
if (remote instanceof MailboxUpdateWithMailbox) {
MailboxUpdateWithMailbox remoteMailbox =
(MailboxUpdateWithMailbox) remote;
return isMailboxUsable(remoteMailbox.getClientSupports(),
remoteMailbox.getMailboxProperties().getServerSupports());
}
return false;
}
/**
* Returns true if we can communicate with a contact that has the given
* client-supported API versions via a mailbox with the given
* server-supported API versions.
*/
private boolean isMailboxUsable(List<MailboxVersion> contactClient,
List<MailboxVersion> server) {
return isClientCompatibleWithServer(contactClient, server)
&& isClientCompatibleWithServer(CLIENT_SUPPORTS, server);
}
/**
* Returns true if our client-supported API versions are compatible with
* our own mailbox's server-supported API versions.
*/
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
private boolean isOwnMailboxUsable(MailboxProperties ownProperties) {
return isClientCompatibleWithServer(CLIENT_SUPPORTS,
ownProperties.getServerSupports());
}
/**
* A container for the latest {@link MailboxUpdate updates} sent to and
* received from a given contact.
*/
private static class Updates {
/**
* The latest update sent to the contact.
*/
private final MailboxUpdate local;
/**
* The latest update received from the contact, or null if no update
* has been received.
*/
@Nullable
private final MailboxUpdate remote;
private Updates(MailboxUpdate local, @Nullable MailboxUpdate remote) {
this.local = local;
this.remote = remote;
}
}
}

View File

@@ -4,22 +4,17 @@ import org.briarproject.bramble.api.FeatureFlags;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.TransactionManager;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.event.EventExecutor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.mailbox.MailboxManager;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
import org.briarproject.bramble.api.mailbox.MailboxVersion;
import org.briarproject.bramble.api.plugin.PluginManager;
import org.briarproject.bramble.api.sync.validation.ValidationManager;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
import java.util.List;
import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -42,8 +37,6 @@ public class MailboxModule {
MailboxUpdateManager mailboxUpdateManager;
@Inject
MailboxFileManager mailboxFileManager;
@Inject
MailboxClientManager mailboxClientManager;
}
@Provides
@@ -133,49 +126,4 @@ public class MailboxModule {
MailboxWorkerFactoryImpl mailboxWorkerFactory) {
return mailboxWorkerFactory;
}
@Provides
MailboxClientFactory provideMailboxClientFactory(
MailboxClientFactoryImpl mailboxClientFactory) {
return mailboxClientFactory;
}
@Provides
MailboxApiCaller provideMailboxApiCaller(
MailboxApiCallerImpl mailboxApiCaller) {
return mailboxApiCaller;
}
@Provides
@Singleton
TorReachabilityMonitor provideTorReachabilityMonitor(
TorReachabilityMonitorImpl reachabilityMonitor) {
return reachabilityMonitor;
}
@Provides
@Singleton
MailboxClientManager provideMailboxClientManager(
@EventExecutor Executor eventExecutor,
@DatabaseExecutor Executor dbExecutor,
TransactionManager db,
ContactManager contactManager,
PluginManager pluginManager,
MailboxSettingsManager mailboxSettingsManager,
MailboxUpdateManager mailboxUpdateManager,
MailboxClientFactory mailboxClientFactory,
TorReachabilityMonitor reachabilityMonitor,
FeatureFlags featureFlags,
LifecycleManager lifecycleManager,
EventBus eventBus) {
MailboxClientManager manager = new MailboxClientManager(eventExecutor,
dbExecutor, db, contactManager, pluginManager,
mailboxSettingsManager, mailboxUpdateManager,
mailboxClientFactory, reachabilityMonitor);
if (featureFlags.shouldEnableMailbox()) {
lifecycleManager.registerService(manager);
eventBus.addListener(manager);
}
return manager;
}
}

View File

@@ -120,8 +120,7 @@ class MailboxPairingTaskImpl implements MailboxPairingTask {
db.transaction(false, txn -> {
mailboxSettingsManager
.setOwnMailboxProperties(txn, ownerProperties);
mailboxSettingsManager.recordSuccessfulConnection(txn, time,
ownerProperties.getServerSupports());
mailboxSettingsManager.recordSuccessfulConnection(txn, time);
// A (possibly new) mailbox is paired. Reset message retransmission
// timers for contacts who doesn't have their own mailbox. This way,
// data stranded on our old mailbox will be re-uploaded to our new.

View File

@@ -80,7 +80,7 @@ class MailboxSettingsManagerImpl implements MailboxSettingsManager {
encodeServerSupports(serverSupports, s);
settingsManager.mergeSettings(txn, s, SETTINGS_NAMESPACE);
for (MailboxHook hook : hooks) {
hook.mailboxPaired(txn, p);
hook.mailboxPaired(txn, p.getOnion(), p.getServerSupports());
}
}
@@ -89,10 +89,6 @@ class MailboxSettingsManagerImpl implements MailboxSettingsManager {
Settings s = new Settings();
s.put(SETTINGS_KEY_ONION, "");
s.put(SETTINGS_KEY_TOKEN, "");
s.put(SETTINGS_KEY_ATTEMPTS, "");
s.put(SETTINGS_KEY_LAST_ATTEMPT, "");
s.put(SETTINGS_KEY_LAST_SUCCESS, "");
s.put(SETTINGS_KEY_SERVER_SUPPORTS, "");
settingsManager.mergeSettings(txn, s, SETTINGS_NAMESPACE);
for (MailboxHook hook : hooks) {
hook.mailboxUnpaired(txn);
@@ -116,39 +112,42 @@ class MailboxSettingsManagerImpl implements MailboxSettingsManager {
serverSupports);
}
@Override
public void recordSuccessfulConnection(Transaction txn, long now)
throws DbException {
recordSuccessfulConnection(txn, now, null);
}
@Override
public void recordSuccessfulConnection(Transaction txn, long now,
List<MailboxVersion> versions) throws DbException {
// if we no longer have a paired mailbox, return
Settings oldSettings =
settingsManager.getSettings(txn, SETTINGS_NAMESPACE);
String onion = oldSettings.get(SETTINGS_KEY_ONION);
String token = oldSettings.get(SETTINGS_KEY_TOKEN);
if (isNullOrEmpty(onion) || isNullOrEmpty(token)) return;
@Nullable List<MailboxVersion> versions) throws DbException {
Settings s = new Settings();
// record the successful connection
// fetch version that the server supports first
List<MailboxVersion> serverSupports;
if (versions == null) {
Settings oldSettings =
settingsManager.getSettings(txn, SETTINGS_NAMESPACE);
serverSupports = parseServerSupports(oldSettings);
} else {
serverSupports = versions;
// store new versions
encodeServerSupports(serverSupports, s);
}
// now record the successful connection
s.putLong(SETTINGS_KEY_LAST_ATTEMPT, now);
s.putLong(SETTINGS_KEY_LAST_SUCCESS, now);
s.putInt(SETTINGS_KEY_ATTEMPTS, 0);
encodeServerSupports(versions, s);
settingsManager.mergeSettings(txn, s, SETTINGS_NAMESPACE);
for (MailboxHook hook : hooks) {
hook.serverSupportedVersionsReceived(txn, versions);
}
// broadcast status event
MailboxStatus status = new MailboxStatus(now, now, 0, versions);
MailboxStatus status = new MailboxStatus(now, now, 0, serverSupports);
txn.attach(new OwnMailboxConnectionStatusEvent(status));
}
@Override
public void recordFailedConnectionAttempt(Transaction txn, long now)
throws DbException {
// if we no longer have a paired mailbox, return
Settings oldSettings =
settingsManager.getSettings(txn, SETTINGS_NAMESPACE);
String onion = oldSettings.get(SETTINGS_KEY_ONION);
String token = oldSettings.get(SETTINGS_KEY_TOKEN);
if (isNullOrEmpty(onion) || isNullOrEmpty(token)) return;
int newAttempts = 1 + oldSettings.getInt(SETTINGS_KEY_ATTEMPTS, 0);
long lastSuccess = oldSettings.getLong(SETTINGS_KEY_LAST_SUCCESS, 0);
Settings newSettings = new Settings();

View File

@@ -25,9 +25,6 @@ import org.briarproject.bramble.api.mailbox.MailboxUpdate;
import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
import org.briarproject.bramble.api.mailbox.MailboxUpdateWithMailbox;
import org.briarproject.bramble.api.mailbox.MailboxVersion;
import org.briarproject.bramble.api.mailbox.event.MailboxPairedEvent;
import org.briarproject.bramble.api.mailbox.event.MailboxUnpairedEvent;
import org.briarproject.bramble.api.mailbox.event.MailboxUpdateSentToNewContactEvent;
import org.briarproject.bramble.api.mailbox.event.RemoteMailboxUpdateEvent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Group;
@@ -41,7 +38,6 @@ import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
import org.briarproject.bramble.api.versioning.ClientVersioningManager.ClientVersioningHook;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -49,9 +45,6 @@ import java.util.Map.Entry;
import javax.annotation.Nullable;
import javax.inject.Inject;
import static java.util.Collections.emptyList;
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
import static org.briarproject.bramble.api.sync.validation.IncomingMessageHook.DeliveryAction.ACCEPT_DO_NOT_SHARE;
@NotNullByDefault
@@ -123,7 +116,7 @@ class MailboxUpdateManagerImpl implements MailboxUpdateManager,
db.addGroup(txn, localGroup);
// Set things up for any pre-existing contacts
for (Contact c : db.getContacts(txn)) {
addingContact(txn, c, false);
addingContact(txn, c);
}
}
@@ -139,17 +132,6 @@ class MailboxUpdateManagerImpl implements MailboxUpdateManager,
@Override
public void addingContact(Transaction txn, Contact c) throws DbException {
addingContact(txn, c, true);
}
/**
* @param attachEvent True if a {@link MailboxUpdateSentToNewContactEvent}
* should be attached to the transaction. We should only do this when
* adding a new contact, not when setting up this client for an existing
* contact.
*/
private void addingContact(Transaction txn, Contact c, boolean attachEvent)
throws DbException {
// Create a group to share with the contact
Group g = getContactGroup(c);
db.addGroup(txn, g);
@@ -161,17 +143,13 @@ class MailboxUpdateManagerImpl implements MailboxUpdateManager,
clientHelper.setContactId(txn, g.getId(), c.getId());
MailboxProperties ownProps =
mailboxSettingsManager.getOwnMailboxProperties(txn);
MailboxUpdate u;
if (ownProps != null) {
// We are paired, create and send props to the newly added contact
u = createAndSendUpdateWithMailbox(txn, c,
ownProps.getServerSupports(), ownProps.getOnion());
createAndSendUpdateWithMailbox(txn, c, ownProps.getServerSupports(),
ownProps.getOnion());
} else {
// Not paired, but we still want to get our clientSupports sent
u = sendUpdateNoMailbox(txn, c);
}
if (attachEvent) {
txn.attach(new MailboxUpdateSentToNewContactEvent(c.getId(), u));
sendUpdateNoMailbox(txn, c);
}
}
@@ -181,103 +159,18 @@ class MailboxUpdateManagerImpl implements MailboxUpdateManager,
}
@Override
public void mailboxPaired(Transaction txn, MailboxProperties p)
throws DbException {
Map<ContactId, MailboxUpdateWithMailbox> localUpdates = new HashMap<>();
public void mailboxPaired(Transaction txn, String ownOnion,
List<MailboxVersion> serverSupports) throws DbException {
for (Contact c : db.getContacts(txn)) {
MailboxUpdateWithMailbox u = createAndSendUpdateWithMailbox(txn, c,
p.getServerSupports(), p.getOnion());
localUpdates.put(c.getId(), u);
}
txn.attach(new MailboxPairedEvent(p, localUpdates));
// Store the list of server-supported versions
try {
storeSentServerSupports(txn, p.getServerSupports());
} catch (FormatException e) {
throw new DbException();
createAndSendUpdateWithMailbox(txn, c, serverSupports, ownOnion);
}
}
@Override
public void mailboxUnpaired(Transaction txn) throws DbException {
Map<ContactId, MailboxUpdate> localUpdates = new HashMap<>();
for (Contact c : db.getContacts(txn)) {
MailboxUpdate u = sendUpdateNoMailbox(txn, c);
localUpdates.put(c.getId(), u);
sendUpdateNoMailbox(txn, c);
}
txn.attach(new MailboxUnpairedEvent(localUpdates));
// Remove the list of server-supported versions
try {
BdfDictionary meta = BdfDictionary.of(new BdfEntry(
GROUP_KEY_SENT_SERVER_SUPPORTS, NULL_VALUE));
clientHelper.mergeGroupMetadata(txn, localGroup.getId(), meta);
} catch (FormatException e) {
throw new DbException();
}
}
@Override
public void serverSupportedVersionsReceived(Transaction txn,
List<MailboxVersion> serverSupports) throws DbException {
try {
List<MailboxVersion> oldServerSupports =
loadSentServerSupports(txn);
if (serverSupports.equals(oldServerSupports)) return;
storeSentServerSupports(txn, serverSupports);
for (Contact c : db.getContacts(txn)) {
Group contactGroup = getContactGroup(c);
LatestUpdate latest =
findLatest(txn, contactGroup.getId(), true);
// This method should only be called when we have a mailbox,
// in which case we should have sent a local update to every
// contact
if (latest == null) throw new DbException();
BdfList body =
clientHelper.getMessageAsList(txn, latest.messageId);
MailboxUpdate oldUpdate = parseUpdate(body);
if (!oldUpdate.hasMailbox()) throw new DbException();
MailboxUpdateWithMailbox newUpdate = updateServerSupports(
(MailboxUpdateWithMailbox) oldUpdate, serverSupports);
storeMessageReplaceLatest(txn, contactGroup.getId(), newUpdate,
latest);
}
} catch (FormatException e) {
throw new DbException();
}
}
private void storeSentServerSupports(Transaction txn,
List<MailboxVersion> serverSupports)
throws DbException, FormatException {
BdfDictionary meta = BdfDictionary.of(new BdfEntry(
GROUP_KEY_SENT_SERVER_SUPPORTS,
encodeSupportsList(serverSupports)));
clientHelper.mergeGroupMetadata(txn, localGroup.getId(), meta);
}
private List<MailboxVersion> loadSentServerSupports(Transaction txn)
throws DbException, FormatException {
BdfDictionary meta = clientHelper.getGroupMetadataAsDictionary(txn,
localGroup.getId());
BdfList serverSupports =
meta.getOptionalList(GROUP_KEY_SENT_SERVER_SUPPORTS);
if (serverSupports == null) return emptyList();
return clientHelper.parseMailboxVersionList(serverSupports);
}
/**
* Returns a new {@link MailboxUpdateWithMailbox} that updates the list
* of server-supported API versions in the given
* {@link MailboxUpdateWithMailbox}.
*/
private MailboxUpdateWithMailbox updateServerSupports(
MailboxUpdateWithMailbox old, List<MailboxVersion> serverSupports) {
MailboxProperties oldProps = old.getMailboxProperties();
MailboxProperties newProps = new MailboxProperties(oldProps.getOnion(),
oldProps.getAuthToken(), serverSupports,
requireNonNull(oldProps.getInboxId()),
requireNonNull(oldProps.getOutboxId()));
return new MailboxUpdateWithMailbox(old.getClientSupports(), newProps);
}
@Override
@@ -346,19 +239,18 @@ class MailboxUpdateManagerImpl implements MailboxUpdateManager,
* supported Mailbox API version(s). All of which the contact needs to
* communicate with our Mailbox.
*/
private MailboxUpdateWithMailbox createAndSendUpdateWithMailbox(
Transaction txn, Contact c, List<MailboxVersion> serverSupports,
String ownOnion) throws DbException {
private void createAndSendUpdateWithMailbox(Transaction txn, Contact c,
List<MailboxVersion> serverSupports, String ownOnion)
throws DbException {
MailboxProperties properties = new MailboxProperties(ownOnion,
new MailboxAuthToken(crypto.generateUniqueId().getBytes()),
serverSupports,
new MailboxFolderId(crypto.generateUniqueId().getBytes()),
new MailboxFolderId(crypto.generateUniqueId().getBytes()));
MailboxUpdateWithMailbox u =
MailboxUpdate u =
new MailboxUpdateWithMailbox(clientSupports, properties);
Group g = getContactGroup(c);
storeMessageReplaceLatest(txn, g.getId(), u);
return u;
}
/**
@@ -367,12 +259,11 @@ class MailboxUpdateManagerImpl implements MailboxUpdateManager,
* Mailbox that they can use. It still includes the list of Mailbox API
* version(s) that we support as a client.
*/
private MailboxUpdate sendUpdateNoMailbox(Transaction txn, Contact c)
private void sendUpdateNoMailbox(Transaction txn, Contact c)
throws DbException {
Group g = getContactGroup(c);
MailboxUpdate u = new MailboxUpdate(clientSupports);
storeMessageReplaceLatest(txn, g.getId(), u);
return u;
}
@Nullable
@@ -397,27 +288,21 @@ class MailboxUpdateManagerImpl implements MailboxUpdateManager,
MailboxUpdate u) throws DbException {
try {
LatestUpdate latest = findLatest(txn, g, true);
storeMessageReplaceLatest(txn, g, u, latest);
long version = latest == null ? 1 : latest.version + 1;
Message m = clientHelper.createMessage(g, clock.currentTimeMillis(),
encodeProperties(version, u));
BdfDictionary meta = new BdfDictionary();
meta.put(MSG_KEY_VERSION, version);
meta.put(MSG_KEY_LOCAL, true);
clientHelper.addLocalMessage(txn, m, meta, true, false);
if (latest != null) {
db.removeMessage(txn, latest.messageId);
}
} catch (FormatException e) {
throw new DbException(e);
}
}
private void storeMessageReplaceLatest(Transaction txn, GroupId g,
MailboxUpdate u, @Nullable LatestUpdate latest)
throws DbException, FormatException {
long version = latest == null ? 1 : latest.version + 1;
Message m = clientHelper.createMessage(g, clock.currentTimeMillis(),
encodeProperties(version, u));
BdfDictionary meta = new BdfDictionary();
meta.put(MSG_KEY_VERSION, version);
meta.put(MSG_KEY_LOCAL, true);
clientHelper.addLocalMessage(txn, m, meta, true, false);
if (latest != null) {
db.removeMessage(txn, latest.messageId);
}
}
@Nullable
private LatestUpdate findLatest(Transaction txn, GroupId g, boolean local)
throws DbException, FormatException {

View File

@@ -1,7 +1,6 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.Cancellable;
import org.briarproject.bramble.api.connection.ConnectionRegistry;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
@@ -13,8 +12,6 @@ import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.mailbox.MailboxFolderId;
import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent;
import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.OutgoingSessionRecord;
import org.briarproject.bramble.api.sync.event.GroupVisibilityUpdatedEvent;
@@ -35,7 +32,6 @@ import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
import static java.lang.Boolean.TRUE;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.logging.Level.INFO;
@@ -62,16 +58,9 @@ class MailboxUploadWorker implements MailboxWorker, ConnectivityObserver,
* <p>
* If there's no data to send, the worker listens for events indicating
* that new data may be ready to send.
* <p>
* Whenever we're directly connected to the contact, the worker doesn't
* check for data to send or start connectivity checks until the contact
* disconnects. However, if the worker has already started writing and
* uploading a file when the contact connects, the worker will finish the
* upload.
*/
private enum State {
CREATED,
CONNECTED_TO_CONTACT,
CHECKING_FOR_DATA,
WAITING_FOR_DATA,
CONNECTIVITY_CHECK,
@@ -106,7 +95,6 @@ class MailboxUploadWorker implements MailboxWorker, ConnectivityObserver,
private final Clock clock;
private final TaskScheduler taskScheduler;
private final EventBus eventBus;
private final ConnectionRegistry connectionRegistry;
private final ConnectivityChecker connectivityChecker;
private final MailboxApiCaller mailboxApiCaller;
private final MailboxApi mailboxApi;
@@ -133,7 +121,6 @@ class MailboxUploadWorker implements MailboxWorker, ConnectivityObserver,
Clock clock,
TaskScheduler taskScheduler,
EventBus eventBus,
ConnectionRegistry connectionRegistry,
ConnectivityChecker connectivityChecker,
MailboxApiCaller mailboxApiCaller,
MailboxApi mailboxApi,
@@ -146,7 +133,6 @@ class MailboxUploadWorker implements MailboxWorker, ConnectivityObserver,
this.clock = clock;
this.taskScheduler = taskScheduler;
this.eventBus = eventBus;
this.connectionRegistry = connectionRegistry;
this.connectivityChecker = connectivityChecker;
this.mailboxApiCaller = mailboxApiCaller;
this.mailboxApi = mailboxApi;
@@ -196,12 +182,6 @@ class MailboxUploadWorker implements MailboxWorker, ConnectivityObserver,
synchronized (lock) {
checkTask = null;
if (state != State.CHECKING_FOR_DATA) return;
// Check whether we're directly connected to the contact. Calling
// this while holding the lock isn't ideal, but it avoids races
if (connectionRegistry.isConnected(contactId)) {
state = State.CONNECTED_TO_CONTACT;
return;
}
}
LOG.info("Checking for data to send");
try {
@@ -348,13 +328,13 @@ class MailboxUploadWorker implements MailboxWorker, ConnectivityObserver,
LOG.info("Uploading file");
mailboxApi.addFile(mailboxProperties, folderId, file);
markMessagesSentOrAcked(sessionRecord);
delete(file);
synchronized (lock) {
if (state != State.WRITING_UPLOADING) return;
state = State.CHECKING_FOR_DATA;
apiCall = null;
this.file = null;
}
delete(file);
checkForDataToSend();
}
@@ -384,14 +364,8 @@ class MailboxUploadWorker implements MailboxWorker, ConnectivityObserver,
onDataToSend();
}
} else if (e instanceof MessageSharedEvent) {
MessageSharedEvent m = (MessageSharedEvent) e;
// If the contact is present in the map (ie the value is not null)
// and the value is true, the message's group is shared with the
// contact and therefore the message may now be sendable
if (m.getGroupVisibility().get(contactId) == TRUE) {
LOG.info("Message shared");
onDataToSend();
}
LOG.info("Message shared");
onDataToSend();
} else if (e instanceof GroupVisibilityUpdatedEvent) {
GroupVisibilityUpdatedEvent g = (GroupVisibilityUpdatedEvent) e;
if (g.getVisibility() == SHARED &&
@@ -399,18 +373,6 @@ class MailboxUploadWorker implements MailboxWorker, ConnectivityObserver,
LOG.info("Group shared");
onDataToSend();
}
} else if (e instanceof ContactConnectedEvent) {
ContactConnectedEvent c = (ContactConnectedEvent) e;
if (c.getContactId().equals(contactId)) {
LOG.info("Contact connected");
onContactConnected();
}
} else if (e instanceof ContactDisconnectedEvent) {
ContactDisconnectedEvent c = (ContactDisconnectedEvent) e;
if (c.getContactId().equals(contactId)) {
LOG.info("Contact disconnected");
onContactDisconnected();
}
}
}
@@ -429,36 +391,4 @@ class MailboxUploadWorker implements MailboxWorker, ConnectivityObserver,
// If we had scheduled a wakeup when data was due to be sent, cancel it
if (wakeupTask != null) wakeupTask.cancel();
}
@EventExecutor
private void onContactConnected() {
Cancellable wakeupTask = null, checkTask = null;
synchronized (lock) {
if (state == State.DESTROYED) return;
// If we're checking for data to send, waiting for data to send,
// or checking connectivity then wait until we disconnect from
// the contact before proceeding. If we're writing or uploading
// a file then continue
if (state == State.CHECKING_FOR_DATA ||
state == State.WAITING_FOR_DATA ||
state == State.CONNECTIVITY_CHECK) {
state = State.CONNECTED_TO_CONTACT;
wakeupTask = this.wakeupTask;
this.wakeupTask = null;
checkTask = this.checkTask;
this.checkTask = null;
}
}
if (wakeupTask != null) wakeupTask.cancel();
if (checkTask != null) checkTask.cancel();
}
@EventExecutor
private void onContactDisconnected() {
synchronized (lock) {
if (state != State.CONNECTED_TO_CONTACT) return;
state = State.CHECKING_FOR_DATA;
}
ioExecutor.execute(this::checkForDataToSend);
}
}

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.connection.ConnectionRegistry;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.event.EventBus;
@@ -26,7 +25,6 @@ class MailboxWorkerFactoryImpl implements MailboxWorkerFactory {
private final Clock clock;
private final TaskScheduler taskScheduler;
private final EventBus eventBus;
private final ConnectionRegistry connectionRegistry;
private final MailboxApiCaller mailboxApiCaller;
private final MailboxApi mailboxApi;
private final MailboxFileManager mailboxFileManager;
@@ -38,7 +36,6 @@ class MailboxWorkerFactoryImpl implements MailboxWorkerFactory {
Clock clock,
TaskScheduler taskScheduler,
EventBus eventBus,
ConnectionRegistry connectionRegistry,
MailboxApiCaller mailboxApiCaller,
MailboxApi mailboxApi,
MailboxFileManager mailboxFileManager,
@@ -48,7 +45,6 @@ class MailboxWorkerFactoryImpl implements MailboxWorkerFactory {
this.clock = clock;
this.taskScheduler = taskScheduler;
this.eventBus = eventBus;
this.connectionRegistry = connectionRegistry;
this.mailboxApiCaller = mailboxApiCaller;
this.mailboxApi = mailboxApi;
this.mailboxFileManager = mailboxFileManager;
@@ -61,9 +57,9 @@ class MailboxWorkerFactoryImpl implements MailboxWorkerFactory {
MailboxProperties properties, MailboxFolderId folderId,
ContactId contactId) {
MailboxUploadWorker worker = new MailboxUploadWorker(ioExecutor, db,
clock, taskScheduler, eventBus, connectionRegistry,
connectivityChecker, mailboxApiCaller, mailboxApi,
mailboxFileManager, properties, folderId, contactId);
clock, taskScheduler, eventBus, connectivityChecker,
mailboxApiCaller, mailboxApi, mailboxFileManager,
properties, folderId, contactId);
eventBus.addListener(worker);
return worker;
}
@@ -92,10 +88,8 @@ class MailboxWorkerFactoryImpl implements MailboxWorkerFactory {
public MailboxWorker createContactListWorkerForOwnMailbox(
ConnectivityChecker connectivityChecker,
MailboxProperties properties) {
OwnMailboxContactListWorker worker = new OwnMailboxContactListWorker(
ioExecutor, db, eventBus, connectivityChecker, mailboxApiCaller,
mailboxApi, mailboxUpdateManager, properties);
eventBus.addListener(worker);
return worker;
return new OwnMailboxContactListWorker(ioExecutor, db, eventBus,
connectivityChecker, mailboxApiCaller, mailboxApi,
mailboxUpdateManager, properties);
}
}

View File

@@ -1,13 +1,9 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.Cancellable;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.mailbox.MailboxFolderId;
import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.TaskScheduler;
import org.briarproject.bramble.mailbox.ConnectivityChecker.ConnectivityObserver;
import java.util.ArrayList;
import java.util.HashMap;
@@ -15,27 +11,17 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
import static java.util.concurrent.TimeUnit.HOURS;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Logger.getLogger;
@ThreadSafe
@NotNullByDefault
class OwnMailboxClient implements MailboxClient, ConnectivityObserver {
/**
* How often to check our own mailbox's connectivity.
* <p>
* Package access for testing.
*/
static final long CONNECTIVITY_CHECK_INTERVAL_MS = HOURS.toMillis(1);
class OwnMailboxClient implements MailboxClient {
private static final Logger LOG =
getLogger(OwnMailboxClient.class.getName());
@@ -43,9 +29,6 @@ class OwnMailboxClient implements MailboxClient, ConnectivityObserver {
private final MailboxWorkerFactory workerFactory;
private final ConnectivityChecker connectivityChecker;
private final TorReachabilityMonitor reachabilityMonitor;
private final TaskScheduler taskScheduler;
private final Executor ioExecutor;
private final MailboxProperties properties;
private final MailboxWorker contactListWorker;
private final Object lock = new Object();
@@ -70,30 +53,14 @@ class OwnMailboxClient implements MailboxClient, ConnectivityObserver {
@GuardedBy("lock")
private final Set<ContactId> assignedForDownload = new HashSet<>();
/**
* Scheduled task for periodically checking whether the mailbox is
* reachable.
*/
@GuardedBy("lock")
@Nullable
private Cancellable connectivityTask = null;
@GuardedBy("lock")
private boolean destroyed = false;
OwnMailboxClient(MailboxWorkerFactory workerFactory,
ConnectivityChecker connectivityChecker,
TorReachabilityMonitor reachabilityMonitor,
TaskScheduler taskScheduler,
@IoExecutor Executor ioExecutor,
MailboxProperties properties) {
if (!properties.isOwner()) throw new IllegalArgumentException();
this.workerFactory = workerFactory;
this.connectivityChecker = connectivityChecker;
this.reachabilityMonitor = reachabilityMonitor;
this.taskScheduler = taskScheduler;
this.ioExecutor = ioExecutor;
this.properties = properties;
contactListWorker = workerFactory.createContactListWorkerForOwnMailbox(
connectivityChecker, properties);
}
@@ -101,7 +68,6 @@ class OwnMailboxClient implements MailboxClient, ConnectivityObserver {
@Override
public void start() {
LOG.info("Started");
checkConnectivity();
contactListWorker.start();
}
@@ -110,26 +76,16 @@ class OwnMailboxClient implements MailboxClient, ConnectivityObserver {
LOG.info("Destroyed");
List<MailboxWorker> uploadWorkers;
MailboxWorker downloadWorker;
Cancellable connectivityTask;
synchronized (lock) {
uploadWorkers = new ArrayList<>(this.uploadWorkers.values());
this.uploadWorkers.clear();
downloadWorker = this.downloadWorker;
this.downloadWorker = null;
connectivityTask = this.connectivityTask;
this.connectivityTask = null;
destroyed = true;
}
// Destroy the workers (with apologies to Mr Marx and Mr Engels)
for (MailboxWorker worker : uploadWorkers) worker.destroy();
if (downloadWorker != null) downloadWorker.destroy();
// If a connectivity check is scheduled, cancel it
if (connectivityTask != null) connectivityTask.cancel();
contactListWorker.destroy();
// The connectivity checker belongs to the client, so it should be
// destroyed. The Tor reachability monitor is shared between clients,
// so it should not be destroyed
connectivityChecker.destroy();
}
@Override
@@ -195,28 +151,4 @@ class OwnMailboxClient implements MailboxClient, ConnectivityObserver {
}
if (toDestroy != null) toDestroy.destroy();
}
private void checkConnectivity() {
synchronized (lock) {
if (destroyed) return;
connectivityTask = null;
}
connectivityChecker.checkConnectivity(properties, this);
// Avoid leaking observer in case destroy() is called concurrently
// before observer is added
boolean removeObserver;
synchronized (lock) {
removeObserver = destroyed;
}
if (removeObserver) connectivityChecker.removeObserver(this);
}
@Override
public void onConnectivityCheckSucceeded() {
synchronized (lock) {
if (destroyed) return;
connectivityTask = taskScheduler.schedule(this::checkConnectivity,
ioExecutor, CONNECTIVITY_CHECK_INTERVAL_MS, MILLISECONDS);
}
}
}

View File

@@ -14,7 +14,6 @@ import java.util.List;
import java.util.logging.Logger;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
@@ -31,7 +30,6 @@ class OwnMailboxConnectivityChecker extends ConnectivityCheckerImpl {
private final TransactionManager db;
private final MailboxSettingsManager mailboxSettingsManager;
@Inject
OwnMailboxConnectivityChecker(Clock clock,
MailboxApiCaller mailboxApiCaller,
MailboxApi mailboxApi,
@@ -59,7 +57,6 @@ class OwnMailboxConnectivityChecker extends ConnectivityCheckerImpl {
private boolean checkConnectivityAndStoreResult(
MailboxProperties properties) throws DbException {
try {
LOG.info("Checking whether own mailbox is reachable");
List<MailboxVersion> serverSupports =
mailboxApi.getServerSupports(properties);
LOG.info("Own mailbox is reachable");

View File

@@ -9,9 +9,9 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
interface UrlConverter {
/**
* Converts a raw onion address, excluding the .onion suffix, into an
* HTTP URL.
*/
String convertOnionToBaseUrl(String onion);
/**
* Converts a raw onion address, excluding the .onion suffix, into an
* HTTP URL.
*/
String convertOnionToBaseUrl(String onion);
}

View File

@@ -44,7 +44,6 @@ import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import static java.lang.Boolean.TRUE;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
@@ -234,13 +233,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
ContactRemovedEvent c = (ContactRemovedEvent) e;
if (c.getContactId().equals(contactId)) interrupt();
} else if (e instanceof MessageSharedEvent) {
MessageSharedEvent m = (MessageSharedEvent) e;
// If the contact is present in the map (ie the value is not null)
// and the value is true, the message's group is shared with the
// contact and therefore the message may now be sendable
if (m.getGroupVisibility().get(contactId) == TRUE) {
generateOffer();
}
generateOffer();
} else if (e instanceof GroupVisibilityUpdatedEvent) {
GroupVisibilityUpdatedEvent g = (GroupVisibilityUpdatedEvent) e;
if (g.getVisibility() == SHARED &&

View File

@@ -14,9 +14,7 @@ import org.briarproject.bramble.api.sync.SyncRecordWriter;
import org.briarproject.bramble.api.transport.StreamWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Logger;
import javax.annotation.concurrent.ThreadSafe;
@@ -63,32 +61,26 @@ class MailboxOutgoingSession extends SimplexOutgoingSession {
@Override
void sendAcks() throws DbException, IOException {
List<MessageId> idsToAck = loadMessageIdsToAck();
int idsSent = 0;
while (idsSent < idsToAck.size() && !isInterrupted()) {
int idsRemaining = idsToAck.size() - idsSent;
long capacity = getRemainingCapacity();
long idCapacity =
(capacity - RECORD_HEADER_BYTES) / MessageId.LENGTH;
if (idCapacity == 0) break; // Out of capacity
int idsInRecord = (int) min(idCapacity, MAX_MESSAGE_IDS);
int idsToSend = min(idsRemaining, idsInRecord);
List<MessageId> acked =
idsToAck.subList(idsSent, idsSent + idsToSend);
recordWriter.writeAck(new Ack(acked));
sessionRecord.onAckSent(acked);
while (!isInterrupted()) {
Collection<MessageId> idsToAck = loadMessageIdsToAck();
if (idsToAck.isEmpty()) break;
recordWriter.writeAck(new Ack(idsToAck));
sessionRecord.onAckSent(idsToAck);
LOG.info("Sent ack");
idsSent += idsToSend;
}
}
private List<MessageId> loadMessageIdsToAck() throws DbException {
private Collection<MessageId> loadMessageIdsToAck() throws DbException {
long idCapacity = (getRemainingCapacity() - RECORD_HEADER_BYTES)
/ MessageId.LENGTH;
if (idCapacity <= 0) return emptyList(); // Out of capacity
int maxMessageIds = (int) min(idCapacity, MAX_MESSAGE_IDS);
Collection<MessageId> ids = db.transactionWithResult(true, txn ->
db.getMessagesToAck(txn, contactId));
db.getMessagesToAck(txn, contactId, maxMessageIds));
if (LOG.isLoggable(INFO)) {
LOG.info(ids.size() + " messages to ack");
}
return new ArrayList<>(ids);
return ids;
}
private long getRemainingCapacity() {

View File

@@ -13,24 +13,21 @@ d Bridge obfs4 45.145.95.6:27015 C5B7CD6946FF10C5B3E89691A7D3F2C122D2117C cert=T
d Bridge obfs4 51.222.13.177:80 5EDAC3B810E12B01F6FD8050D2FD3E277B289A08 cert=2uplIpLQ0q9+0qMFrK5pkaYRDOe460LL9WHBvatgkuRr/SL31wBOEupaMMJ6koRE6Ld0ew iat-mode=0
n Bridge obfs4 46.226.107.197:10300 A38FD6BDFD902882F5F5B9B7CCC95602A20B0BC4 cert=t8tA9q2AeGlmp/dO6oW9bkY5RqqmvqjArCEM9wjJoDnk6XtnaejkF0JTA7VamdyOzcvuBg iat-mode=0
n Bridge obfs4 185.181.11.86:443 A961609729E7FDF520B4E81F1F1B8FA1045285C3 cert=e5faG9Zk4Ni+e7z2YgGfevyKPQlMvkVGi4ublSsHYjaBovKeNXpOhbeFxzbZZoAzxAoGUQ iat-mode=0
n Bridge obfs4 85.242.211.221:8042 A36A938DD7FDB8BACC846BA326EE0BA0D89A9252 cert=1AN6Pt1eFca3Y/WYD2TGAU3Al9cO4eouXE9SX63s66Z/ks3tVmgQ5GeXi1B5DOvx6Il7Zw iat-mode=0
n Bridge obfs4 74.104.165.202:9002 EF432018A6AA5D970B2F84E39CD30A147030141C cert=PhppfUusY85dHGvWtGTybZ1fED4DtbHmALkNMIOIYrAz1B4xN7/2a5gyiZe1epju1BOHVg iat-mode=0
n Bridge obfs4 93.95.226.151:41185 460B0CFFC0CF1D965F3DE064E08BA1915E7C916A cert=inluPzp5Jp5OzZar1eQb4dcQ/YlAj/v0kHAUCoCr3rmLt03+pVuVTjoH4mRy4+acXpn+Gw iat-mode=0
n Bridge obfs4 120.29.217.52:5223 40FE3DB9800272F9CDC76422F8ED7883280EE96D cert=/71PS4l8c/XJ4DIItlH9xMqNvPFg2RUTrHvPlQWh48u5et8h/yyyjCcYphUadDsfBWpaGQ iat-mode=0
n Bridge obfs4 76.255.201.112:8888 96CF36C2ECCFB7376AB6BE905BECD2C2AE8AEFCD cert=+q0pjaiM0JMqHL/BKqCRD+pjflaw/S406eUDF7CnFgamvQW3l2HVLJhQ6uX9P8zff0PLGg iat-mode=0
n Bridge obfs4 65.108.159.114:14174 E1AD374BA9F34BD98862D128AC54D40C7DC138AE cert=YMkxMSBN2OOd99AkJpFaEUyKkdqZgJt9oVJEgO1QnT37n/Vc2yR4nhx4k4VkPLfEP1f4eg iat-mode=0
n Bridge obfs4 185.177.207.138:8443 53716FE26F23C8C6A71A2BC5D9D8DC64747278C7 cert=6jcYVilMEzxdsWghSrQFpYYJlkkir/GPIXw/EnddUK3S8ToVpMG8u1SwMOEdEs735RrMHw iat-mode=0
n Bridge obfs4 176.123.2.253:1933 B855D141CE6C4DE0F7EA4AAED83EBA8373FA8191 cert=1rOoSaRagc6PPR//paIl+ukv1N+xWKCdBXMFxK0k/moEwH0lk5bURBrUDzIX35fVzaiicQ iat-mode=0
n Bridge obfs4 5.252.176.61:9418 3E61130100AD827AB9CB33DAC052D9BC49A39509 cert=/aMyBPnKbQFISithD3i1KHUdpWeMpWG3SvUpq1YWCf2EQohFxQfw+646gW1knm4BI/DLRA iat-mode=0
n Bridge obfs4 202.61.224.111:6902 A4F91299763DB925AE3BD29A0FC1A9821E5D9BAE cert=NBKm2MJ83wMvYShkqpD5RrbDtW5YpIZrFNnMw7Dj1XOM3plU60Bh4eziaQXe8fGtb8ZqKg iat-mode=0
n Bridge obfs4 87.121.72.109:9002 C8081D4731C953FA4AE166946E72B29153351E34 cert=bikAqxKV6Ch5gFCBTdPI28VeShYa1ZgkLmvc7YZNLWFsFZoaCULL/3AQKjpIfvSiJs5jGQ iat-mode=0
n Bridge obfs4 172.104.17.96:17900 B6B37AC96E163D0A5ECE55826D17B50B70F0A7F8 cert=gUz7svhPxoALgeN4lMYrXK7NBnaDqwu6SKRJOhaO9IIMBpnB8UhMCMKzzMho3b0RxWzBVg iat-mode=0
n Bridge obfs4 70.34.249.113:443 F441B16ABB1055794C2CE01821FC05047B2C8CFC cert=MauLNoyq8EwjY4Qe0oASYzs2hXdSjNgy+BtP9oo1naHhRsyKTtAZzeNv08RnzWjMJrTwcg iat-mode=0
n Bridge obfs4 85.212.104.44:27623 9000BDF7063F808E554C320545BCF264222CDFE9 cert=eKSXeJLnFv6RDAap5vM2sqsi8GIWhlMi5prs8hu0HTKWTH9KjZhhoj3Cg/gIuoL8n8TXGQ iat-mode=0
n Bridge obfs4 104.168.68.90:443 ED55B3C321E44EA7E50EF568C8A63CF75E89A58C cert=fgonxDvltTp8nmcOE9sUG94eOAALxETVVXAwnTZJLPpf7rjPuTp+abKl4VyFkxfcLRr5KQ iat-mode=0
n Bridge obfs4 158.247.207.151:443 6170ADBBB6C1859A8E7E4416BB8AB3AF471AE47F cert=Od4izlwLnXcq7LMSOJtnZLtklaUn+X+gPcBwN7RUEkk9rqxRRYNHW7as8g6+jheDsazxAQ iat-mode=0
n Bridge obfs4 45.142.181.131:42069 6EBCF6B02DA2B982F4080A7119D737366AFB74FA cert=9HyWH/BCwWzNirZdTQtluCgJk+gFhpOqydIuyQ1iDvpnqsAynKF+zcPE/INZFefm86UlBg iat-mode=0
n Bridge obfs4 85.214.28.204:47111 78A36E46BB082A471848239D3F4390A8F8C6084D cert=96sr3eaUFBDu4wFVAQIfNFElh0UNuutJ/3/Fh2Vu2PHfacQ8bwfY02bwG351U8BZpLnfUQ iat-mode=0
n Bridge obfs4 152.67.77.101:4096 B82DB9CDDF887AB8A859420E07DF298E30AF8A6E cert=21OWn3yFo+hulmQNAOtF5uwwOqWtdT5PrLhk8BG9DpOd0/k5DEkQEYPyDdXbS9nZ0E5BJA iat-mode=0
v Bridge 135.181.113.164:54444 74AF4CCA614C454B7D3E81FF8BACD78CEBC7D7DE
v Bridge 92.243.15.235:9001 477EAD3C04036B48235F1F27FC91420A286A4B7F
v Bridge 77.96.91.103:443 ED000A75B79A58F1D83A4D1675C2A9395B71BE8E
v Bridge 213.108.108.145:17674 A39C0FE47963B6E8CFE9815549864DE544935A31
v Bridge 185.189.195.124:8199 A1F3EE78F9C2343668E68FEB84358A4C742831A5
v Bridge 135.23.182.26:11393 6E9A100D1E0570F0012735D64EEB4CB62AC258D9
m Bridge meek_lite 192.0.2.2:2 97700DFE9F483596DDA6264C4D7DF7641E1E39CE url=https://meek.azureedge.net/ front=ajax.aspnetcdn.com

View File

@@ -10,8 +10,6 @@ import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.bramble.test.TestDnsModule;
import org.briarproject.bramble.test.TestSocksModule;
import java.util.concurrent.Executor;
@@ -22,9 +20,7 @@ import dagger.Component;
@Singleton
@Component(modules = {
BrambleCoreIntegrationTestModule.class,
BrambleCoreModule.class,
TestDnsModule.class,
TestSocksModule.class
BrambleCoreModule.class
})
interface ContactExchangeIntegrationTestComponent
extends BrambleCoreIntegrationTestEagerSingletons {

View File

@@ -70,7 +70,6 @@ import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static java.util.concurrent.TimeUnit.HOURS;
import static org.briarproject.bramble.api.db.DatabaseComponent.TIMER_NOT_STARTED;
import static org.briarproject.bramble.api.record.Record.RECORD_HEADER_BYTES;
@@ -284,16 +283,12 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
temporary, null);
oneOf(database).mergeMessageMetadata(txn, messageId, metadata);
oneOf(database).commitTransaction(txn);
// Broadcast events for message being added and changing state
// The message was added, so the listeners should be called
oneOf(eventBus).broadcast(with(any(MessageAddedEvent.class)));
oneOf(eventBus).broadcast(with(any(
MessageStateChangedEvent.class)));
// If message is shared, get group visibility and broadcast event
if (shared) {
oneOf(database).getGroupVisibility(txn, groupId);
will(returnValue(singletonMap(contactId, true)));
if (shared)
oneOf(eventBus).broadcast(with(any(MessageSharedEvent.class)));
}
}});
DatabaseComponent db = createDatabaseComponent(database, eventBus,
eventExecutor, shutdownManager);
@@ -394,7 +389,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
try {
db.transaction(true, transaction ->
db.getMessagesToAck(transaction, contactId));
db.getMessagesToAck(transaction, contactId, 123));
fail();
} catch (NoSuchContactException expected) {
// Expected
@@ -699,11 +694,11 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
throws Exception {
context.checking(new Expectations() {{
// Check whether the message is in the DB (which it's not)
exactly(16).of(database).startTransaction();
exactly(15).of(database).startTransaction();
will(returnValue(txn));
exactly(16).of(database).containsMessage(txn, messageId);
exactly(15).of(database).containsMessage(txn, messageId);
will(returnValue(false));
exactly(16).of(database).abortTransaction(txn);
exactly(15).of(database).abortTransaction(txn);
// Allow other checks to pass
allowing(database).containsContact(txn, contactId);
will(returnValue(true));
@@ -727,14 +722,6 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
// Expected
}
try {
db.transaction(true, transaction ->
db.getGroupId(transaction, messageId));
fail();
} catch (NoSuchMessageException expected) {
// Expected
}
try {
db.transaction(true, transaction ->
db.getMessage(transaction, messageId));
@@ -1409,7 +1396,14 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
will(returnValue(txn));
oneOf(database).containsContact(txn, contactId);
will(returnValue(true));
oneOf(database).lowerAckFlag(txn, contactId, acked);
// First message is still visible to the contact - flag lowered
oneOf(database).containsVisibleMessage(txn, contactId, messageId);
will(returnValue(true));
// Second message is no longer visible - flag not lowered
oneOf(database).containsVisibleMessage(txn, contactId, messageId1);
will(returnValue(false));
oneOf(database)
.lowerAckFlag(txn, contactId, singletonList(messageId));
oneOf(database).commitTransaction(txn);
}});
DatabaseComponent db = createDatabaseComponent(database, eventBus,
@@ -1886,16 +1880,12 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
oneOf(database).containsMessage(txn, messageId);
will(returnValue(true));
oneOf(database).getMessageDependents(txn, messageId);
// Broadcast events for message being added and changing state
// broadcast for message added event
oneOf(eventBus).broadcast(with(any(MessageAddedEvent.class)));
oneOf(eventBus).broadcast(with(any(
MessageStateChangedEvent.class)));
// If message is shared, get group visibility and broadcast event
if (shared) {
oneOf(database).getGroupVisibility(txn, groupId);
will(returnValue(singletonMap(contactId, true)));
if (shared)
oneOf(eventBus).broadcast(with(any(MessageSharedEvent.class)));
}
// endTransaction()
oneOf(database).commitTransaction(txn);
// close()

View File

@@ -168,7 +168,6 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
assertTrue(db.containsContact(txn, contactId));
assertTrue(db.containsGroup(txn, groupId));
assertTrue(db.containsMessage(txn, messageId));
assertEquals(groupId, db.getGroupId(txn, messageId));
assertArrayEquals(message.getBody(),
db.getMessage(txn, messageId).getBody());

View File

@@ -40,8 +40,6 @@ public class ContactMailboxClientTest extends BrambleMockTestCase {
@Test
public void testStartAndDestroyWithNoContactsAssigned() {
client.start();
expectDestroyConnectivityChecker();
client.destroy();
}
@@ -56,7 +54,6 @@ public class ContactMailboxClientTest extends BrambleMockTestCase {
// When the client is destroyed, the worker should be destroyed
expectDestroyWorker(uploadWorker);
expectDestroyConnectivityChecker();
client.destroy();
}
@@ -74,7 +71,6 @@ public class ContactMailboxClientTest extends BrambleMockTestCase {
client.deassignContactForUpload(contactId);
context.assertIsSatisfied();
expectDestroyConnectivityChecker();
client.destroy();
}
@@ -89,7 +85,6 @@ public class ContactMailboxClientTest extends BrambleMockTestCase {
// When the client is destroyed, the worker should be destroyed
expectDestroyWorker(downloadWorker);
expectDestroyConnectivityChecker();
client.destroy();
}
@@ -107,7 +102,6 @@ public class ContactMailboxClientTest extends BrambleMockTestCase {
client.deassignContactForDownload(contactId);
context.assertIsSatisfied();
expectDestroyConnectivityChecker();
client.destroy();
}
@@ -134,10 +128,4 @@ public class ContactMailboxClientTest extends BrambleMockTestCase {
oneOf(worker).destroy();
}});
}
private void expectDestroyConnectivityChecker() {
context.checking(new Expectations() {{
oneOf(connectivityChecker).destroy();
}});
}
}

View File

@@ -1,8 +1,6 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.WeakSingletonProvider;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.mailbox.InvalidMailboxIdException;
import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
import org.briarproject.bramble.api.mailbox.MailboxFileId;
import org.briarproject.bramble.api.mailbox.MailboxFolderId;
@@ -13,7 +11,6 @@ import org.briarproject.bramble.mailbox.MailboxApi.MailboxFile;
import org.briarproject.bramble.mailbox.MailboxApi.TolerableFailureException;
import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
@@ -25,14 +22,11 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nonnull;
import javax.net.SocketFactory;
import okhttp3.OkHttpClient;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.SETUP_TOKEN;
import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.URL_BASE;
import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.createMailboxApi;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.test.TestUtils.isOptionalTestEnabled;
@@ -40,58 +34,31 @@ import static org.briarproject.bramble.test.TestUtils.readBytes;
import static org.briarproject.bramble.test.TestUtils.writeBytes;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
public class MailboxIntegrationTest extends BrambleTestCase {
public class MailboxApiIntegrationTest extends BrambleTestCase {
@Rule
public TemporaryFolder folder = new TemporaryFolder();
private static final String URL_BASE = "http://127.0.0.1:8000";
private static final MailboxAuthToken SETUP_TOKEN;
private static final MailboxApi api = createMailboxApi();
static {
try {
SETUP_TOKEN = MailboxAuthToken.fromString(
"54686973206973206120736574757020746f6b656e20666f722042726961722e");
} catch (InvalidMailboxIdException e) {
throw new IllegalStateException();
}
}
private static final OkHttpClient client = new OkHttpClient.Builder()
.socketFactory(SocketFactory.getDefault())
.connectTimeout(60_000, MILLISECONDS)
.build();
private static final WeakSingletonProvider<OkHttpClient>
httpClientProvider =
new WeakSingletonProvider<OkHttpClient>() {
@Override
@Nonnull
public OkHttpClient createInstance() {
return client;
}
};
// We aren't using a real onion address, so use the given address verbatim
private static final UrlConverter urlConverter = onion -> onion;
private static final MailboxApiImpl api =
new MailboxApiImpl(httpClientProvider, urlConverter);
// needs to be static to keep values across different tests
private static MailboxProperties ownerProperties;
/**
* Called before each test to make sure the mailbox is setup once
* before starting with individual tests.
* {@link BeforeClass} needs to be static, so we can't use the API class.
*/
@Before
public void ensureSetup() throws IOException, ApiException {
@BeforeClass
public static void setUp() throws IOException, ApiException {
// Skip this test unless it's explicitly enabled in the environment
assumeTrue(isOptionalTestEnabled(MailboxIntegrationTest.class));
assumeTrue(isOptionalTestEnabled(MailboxApiIntegrationTest.class));
if (ownerProperties != null) return;
assertNull(ownerProperties);
MailboxProperties setupProperties = new MailboxProperties(
URL_BASE, SETUP_TOKEN, new ArrayList<>());
ownerProperties = api.setup(setupProperties);
@@ -100,7 +67,7 @@ public class MailboxIntegrationTest extends BrambleTestCase {
@AfterClass
// we can't test wiping as a regular test as it stops the mailbox
public static void wipe() throws IOException, ApiException {
if (!isOptionalTestEnabled(MailboxIntegrationTest.class)) return;
if (!isOptionalTestEnabled(MailboxApiIntegrationTest.class)) return;
api.wipeMailbox(ownerProperties);

View File

@@ -1,929 +0,0 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.db.TransactionManager;
import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import org.briarproject.bramble.api.mailbox.MailboxStatus;
import org.briarproject.bramble.api.mailbox.MailboxUpdate;
import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
import org.briarproject.bramble.api.mailbox.MailboxUpdateWithMailbox;
import org.briarproject.bramble.api.mailbox.MailboxVersion;
import org.briarproject.bramble.api.mailbox.event.MailboxPairedEvent;
import org.briarproject.bramble.api.mailbox.event.MailboxUnpairedEvent;
import org.briarproject.bramble.api.mailbox.event.OwnMailboxConnectionStatusEvent;
import org.briarproject.bramble.api.mailbox.event.RemoteMailboxUpdateEvent;
import org.briarproject.bramble.api.plugin.Plugin.State;
import org.briarproject.bramble.api.plugin.PluginManager;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.event.TransportActiveEvent;
import org.briarproject.bramble.api.plugin.event.TransportInactiveEvent;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.DbExpectations;
import org.briarproject.bramble.test.RunAction;
import org.jmock.Expectations;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import javax.annotation.Nullable;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static org.briarproject.bramble.api.mailbox.MailboxConstants.CLIENT_SUPPORTS;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
import static org.briarproject.bramble.api.plugin.Plugin.State.ENABLING;
import static org.briarproject.bramble.api.plugin.TorConstants.ID;
import static org.briarproject.bramble.test.TestUtils.getContact;
import static org.briarproject.bramble.test.TestUtils.getMailboxProperties;
public class MailboxClientManagerTest extends BrambleMockTestCase {
private final Executor eventExecutor =
context.mock(Executor.class, "eventExecutor");
private final Executor dbExecutor =
context.mock(Executor.class, "dbExecutor");
private final TransactionManager db =
context.mock(TransactionManager.class);
private final ContactManager contactManager =
context.mock(ContactManager.class);
private final PluginManager pluginManager =
context.mock(PluginManager.class);
private final MailboxSettingsManager mailboxSettingsManager =
context.mock(MailboxSettingsManager.class);
private final MailboxUpdateManager mailboxUpdateManager =
context.mock(MailboxUpdateManager.class);
private final MailboxClientFactory mailboxClientFactory =
context.mock(MailboxClientFactory.class);
private final TorReachabilityMonitor reachabilityMonitor =
context.mock(TorReachabilityMonitor.class);
private final DuplexPlugin plugin = context.mock(DuplexPlugin.class);
private final MailboxClient ownClient =
context.mock(MailboxClient.class, "ownClient");
private final MailboxClient contactClient =
context.mock(MailboxClient.class, "contactClient");
private final MailboxClientManager manager =
new MailboxClientManager(eventExecutor, dbExecutor, db,
contactManager, pluginManager, mailboxSettingsManager,
mailboxUpdateManager, mailboxClientFactory,
reachabilityMonitor);
private final Contact contact = getContact();
private final List<MailboxVersion> incompatibleVersions =
singletonList(new MailboxVersion(999, 0));
private final MailboxProperties ownProperties =
getMailboxProperties(true, CLIENT_SUPPORTS);
private final MailboxProperties localProperties =
getMailboxProperties(false, CLIENT_SUPPORTS);
private final MailboxProperties remoteProperties =
getMailboxProperties(false, CLIENT_SUPPORTS);
private final MailboxProperties remotePropertiesForNewMailbox =
getMailboxProperties(false, CLIENT_SUPPORTS);
private final MailboxUpdate localUpdateWithoutMailbox =
new MailboxUpdate(CLIENT_SUPPORTS);
private final MailboxUpdate remoteUpdateWithoutMailbox =
new MailboxUpdate(CLIENT_SUPPORTS);
private final MailboxUpdate remoteUpdateWithIncompatibleClientVersions =
new MailboxUpdate(incompatibleVersions);
private final MailboxUpdateWithMailbox localUpdateWithMailbox =
new MailboxUpdateWithMailbox(CLIENT_SUPPORTS, localProperties);
private final MailboxUpdateWithMailbox remoteUpdateWithMailbox =
new MailboxUpdateWithMailbox(CLIENT_SUPPORTS, remoteProperties);
private final MailboxUpdateWithMailbox remoteUpdateWithNewMailbox =
new MailboxUpdateWithMailbox(CLIENT_SUPPORTS,
remotePropertiesForNewMailbox);
@Test
public void testLoadsMailboxUpdatesAtStartupWhenOffline() throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We're offline so there's nothing
// else to do.
expectLoadUpdates(localUpdateWithoutMailbox,
remoteUpdateWithoutMailbox, null);
expectCheckPluginState(ENABLING);
manager.startService();
// At shutdown there should be no clients to destroy. The manager
// should destroy the reachability monitor.
expectRunTaskOnEventExecutor();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testLoadsMailboxUpdatesAtStartupWhenOnline() throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We're online but we don't have a
// mailbox and neither does the contact, so there's nothing else to do.
expectLoadUpdates(localUpdateWithoutMailbox,
remoteUpdateWithoutMailbox, null);
expectCheckPluginState(ACTIVE);
manager.startService();
// At shutdown there should be no clients to destroy. The manager
// should destroy the reachability monitor.
expectRunTaskOnEventExecutor();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testAssignsContactToOurMailboxIfContactHasNoMailbox()
throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We have a mailbox but the contact
// doesn't.
//
// We're online, so the manager should create a client for our own
// mailbox and assign the contact to it for upload and download.
expectLoadUpdates(localUpdateWithMailbox,
remoteUpdateWithoutMailbox, ownProperties);
expectCheckPluginState(ACTIVE);
expectCreateClientForOwnMailbox();
expectAssignContactToOwnMailboxForDownload();
expectAssignContactToOwnMailboxForUpload();
manager.startService();
// At shutdown the manager should destroy the client for our own
// mailbox and the reachability monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForOwnMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testDoesNotAssignContactToOurMailboxIfContactHasNotSentUpdate()
throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We have a mailbox but the contact
// has never sent us an update, so the remote update is null.
//
// We're online, so the manager should create a client for our own
// mailbox. We don't know what API versions the contact supports,
// if any, so the contact should not be assigned to our mailbox.
expectLoadUpdates(localUpdateWithMailbox, null, ownProperties);
expectCheckPluginState(ACTIVE);
expectCreateClientForOwnMailbox();
manager.startService();
// At shutdown the manager should destroy the client for our own
// mailbox and the reachability monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForOwnMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testDoesNotAssignContactToOurMailboxIfContactHasIncompatibleClientVersions()
throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We have a mailbox but the contact
// doesn't. The contact's client API versions are incompatible with
// our mailbox.
//
// We're online, so the manager should create a client for our own
// mailbox. The contact's client API versions are incompatible with
// our mailbox, so the contact should not be assigned to our mailbox.
expectLoadUpdates(localUpdateWithMailbox,
remoteUpdateWithIncompatibleClientVersions, ownProperties);
expectCheckPluginState(ACTIVE);
expectCreateClientForOwnMailbox();
manager.startService();
// At shutdown the manager should destroy the client for our own
// mailbox and the reachability monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForOwnMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testAssignsContactToContactMailboxIfWeHaveNoMailbox()
throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We don't have a mailbox but the
// contact does.
//
// We're online, so the manager should create a client for the
// contact's mailbox and assign the contact to it for upload and
// download.
expectLoadUpdates(localUpdateWithoutMailbox,
remoteUpdateWithMailbox, null);
expectCheckPluginState(ACTIVE);
expectCreateClientForContactMailbox();
expectAssignContactToContactMailboxForDownload(remoteProperties);
expectAssignContactToContactMailboxForUpload(remoteProperties);
manager.startService();
// At shutdown the manager should destroy the client for the contact's
// mailbox and the reachability monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForContactMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testAssignsContactToBothMailboxesIfWeBothHaveMailboxes()
throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We have a mailbox and so does the
// contact.
//
// We're online, so the manager should create clients for the
// contact's mailbox and our mailbox. The manager should assign the
// contact to the contact's mailbox for upload and our mailbox for
// download.
expectLoadUpdates(localUpdateWithMailbox,
remoteUpdateWithMailbox, ownProperties);
expectCheckPluginState(ACTIVE);
expectCreateClientForContactMailbox();
expectAssignContactToContactMailboxForUpload(remoteProperties);
expectCreateClientForOwnMailbox();
expectAssignContactToOwnMailboxForDownload();
manager.startService();
// At shutdown the manager should destroy the client for the contact's
// mailbox, the client for our own mailbox, and the reachability
// monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForContactMailbox();
expectDestroyClientForOwnMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testCreatesClientsWhenTorBecomesActive() throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We have a mailbox but the contact
// doesn't. We're offline so there's nothing else to do.
expectLoadUpdates(localUpdateWithMailbox,
remoteUpdateWithoutMailbox, ownProperties);
expectCheckPluginState(ENABLING);
manager.startService();
// When we come online, the manager should create a client for our own
// mailbox and assign the contact to it for upload and download.
expectCreateClientForOwnMailbox();
expectAssignContactToOwnMailboxForDownload();
expectAssignContactToOwnMailboxForUpload();
manager.eventOccurred(new TransportActiveEvent(ID));
// When we go offline, the manager should destroy the client for our
// own mailbox.
expectDestroyClientForOwnMailbox();
manager.eventOccurred(new TransportInactiveEvent(ID));
// At shutdown the manager should destroy the reachability monitor.
expectRunTaskOnEventExecutor();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testAssignsContactToOurMailboxWhenPaired() throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We're online but we don't have a
// mailbox and neither does the contact, so there's nothing else to do.
expectLoadUpdates(localUpdateWithoutMailbox,
remoteUpdateWithoutMailbox, null);
expectCheckPluginState(ACTIVE);
manager.startService();
// When we pair a mailbox, the manager should create a client for our
// mailbox and assign the contact to our mailbox for upload and
// download.
expectCreateClientForOwnMailbox();
expectAssignContactToOwnMailboxForUpload();
expectAssignContactToOwnMailboxForDownload();
manager.eventOccurred(new MailboxPairedEvent(ownProperties,
singletonMap(contact.getId(), localUpdateWithMailbox)));
// At shutdown the manager should destroy the client for our mailbox
// and the reachability monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForOwnMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testReassignsContactToOurMailboxWhenPaired() throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. The contact has a mailbox but we
// don't.
//
// We're online, so the manager should create a client for the
// contact's mailbox and assign the contact to it for upload and
// download.
expectLoadUpdates(localUpdateWithoutMailbox,
remoteUpdateWithMailbox, null);
expectCheckPluginState(ACTIVE);
expectCreateClientForContactMailbox();
expectAssignContactToContactMailboxForDownload(remoteProperties);
expectAssignContactToContactMailboxForUpload(remoteProperties);
manager.startService();
// When we pair a mailbox, the manager should create a client for our
// mailbox and reassign the contact to our mailbox for download.
expectCreateClientForOwnMailbox();
expectDeassignContactFromContactMailboxForDownload();
expectAssignContactToOwnMailboxForDownload();
manager.eventOccurred(new MailboxPairedEvent(ownProperties,
singletonMap(contact.getId(), localUpdateWithMailbox)));
// At shutdown the manager should destroy the client for the contact's
// mailbox, the client for our own mailbox, and the reachability
// monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForContactMailbox();
expectDestroyClientForOwnMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testDoesNotAssignContactWhenPairedIfContactHasNotSentUpdate()
throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We don't have a mailbox and the
// contact has never sent us an update, so the remote update is null.
expectLoadUpdates(localUpdateWithoutMailbox, null, null);
expectCheckPluginState(ACTIVE);
manager.startService();
// When we pair a mailbox, the manager should create a client for our
// mailbox. We don't know whether the contact can use our mailbox, so
// the contact should not be assigned to our mailbox.
expectCreateClientForOwnMailbox();
manager.eventOccurred(new MailboxPairedEvent(ownProperties,
singletonMap(contact.getId(), localUpdateWithMailbox)));
// At shutdown the manager should destroy the client for our mailbox
// and the reachability monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForOwnMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testDoesNotAssignContactWhenPairedIfContactHasIncompatibleClientVersions()
throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We don't have a mailbox and neither
// does the contact. The contact's client API versions are
// incompatible with our mailbox.
expectLoadUpdates(localUpdateWithoutMailbox,
remoteUpdateWithIncompatibleClientVersions, null);
expectCheckPluginState(ACTIVE);
manager.startService();
// When we pair a mailbox, the manager should create a client for our
// mailbox. The contact's client API versions are incompatible with
// our mailbox, so the contact should not be assigned to our mailbox.
expectCreateClientForOwnMailbox();
manager.eventOccurred(new MailboxPairedEvent(ownProperties,
singletonMap(contact.getId(), localUpdateWithMailbox)));
// At shutdown the manager should destroy the client for our mailbox
// and the reachability monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForOwnMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testReassignsContactToContactMailboxWhenUnpaired()
throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We have a mailbox and so does the
// contact.
//
// We're online, so the manager should create clients for the
// contact's mailbox and our mailbox. The manager should assign the
// contact to the contact's mailbox for upload and our mailbox for
// download.
expectLoadUpdates(localUpdateWithMailbox,
remoteUpdateWithMailbox, ownProperties);
expectCheckPluginState(ACTIVE);
expectCreateClientForContactMailbox();
expectAssignContactToContactMailboxForUpload(remoteProperties);
expectCreateClientForOwnMailbox();
expectAssignContactToOwnMailboxForDownload();
manager.startService();
// When we unpair our mailbox, the manager should destroy the client
// for our mailbox and reassign the contact to the contact's mailbox
// for download.
expectDestroyClientForOwnMailbox();
expectAssignContactToContactMailboxForDownload(remoteProperties);
manager.eventOccurred(new MailboxUnpairedEvent(
singletonMap(contact.getId(), localUpdateWithoutMailbox)));
// At shutdown the manager should destroy the client for the contact's
// mailbox and the reachability monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForContactMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testDeassignsContactForUploadAndDownloadWhenContactRemoved()
throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We have a mailbox but the contact
// doesn't.
//
// We're online, so the manager should create a client for our mailbox.
// The manager should assign the contact to our mailbox for upload and
// download.
expectLoadUpdates(localUpdateWithMailbox,
remoteUpdateWithoutMailbox, ownProperties);
expectCheckPluginState(ACTIVE);
expectCreateClientForOwnMailbox();
expectAssignContactToOwnMailboxForUpload();
expectAssignContactToOwnMailboxForDownload();
manager.startService();
// When the contact is removed, the manager should deassign the contact
// from our mailbox for upload and download.
expectDeassignContactFromOwnMailboxForUpload();
expectDeassignContactFromOwnMailboxForDownload();
manager.eventOccurred(new ContactRemovedEvent(contact.getId()));
// At shutdown the manager should destroy the client for our mailbox
// and the reachability monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForOwnMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testDeassignsContactForDownloadWhenContactRemoved()
throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We have a mailbox and so does the
// contact.
//
// We're online, so the manager should create clients for the
// contact's mailbox and our mailbox. The manager should assign the
// contact to the contact's mailbox for upload and our mailbox for
// download.
expectLoadUpdates(localUpdateWithMailbox,
remoteUpdateWithMailbox, ownProperties);
expectCheckPluginState(ACTIVE);
expectCreateClientForContactMailbox();
expectAssignContactToContactMailboxForUpload(remoteProperties);
expectCreateClientForOwnMailbox();
expectAssignContactToOwnMailboxForDownload();
manager.startService();
// When the contact is removed, the manager should destroy the client
// for the contact's mailbox and deassign the contact from our mailbox
// for download.
expectDestroyClientForContactMailbox();
expectDeassignContactFromOwnMailboxForDownload();
manager.eventOccurred(new ContactRemovedEvent(contact.getId()));
// At shutdown the manager should destroy the client for our mailbox
// and the reachability monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForOwnMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testAssignsContactToContactMailboxWhenContactPairsMailbox()
throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We're online but we don't have a
// mailbox and neither does the contact, so there's nothing else to do.
expectLoadUpdates(localUpdateWithoutMailbox,
remoteUpdateWithoutMailbox, null);
expectCheckPluginState(ACTIVE);
manager.startService();
// When the contact pairs a mailbox, the manager should create a client
// for the contact's mailbox and assign the contact to the contact's
// mailbox for upload and download.
expectCreateClientForContactMailbox();
expectAssignContactToContactMailboxForUpload(remoteProperties);
expectAssignContactToContactMailboxForDownload(remoteProperties);
manager.eventOccurred(new RemoteMailboxUpdateEvent(contact.getId(),
remoteUpdateWithMailbox));
// At shutdown the manager should destroy the client for the contact's
// mailbox and the reachability monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForContactMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testReassignsContactForUploadWhenContactPairsMailbox()
throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We have a mailbox but the contact
// doesn't.
//
// We're online, so the manager should create a client for our mailbox.
// The manager should assign the contact to our mailbox for upload and
// download.
expectLoadUpdates(localUpdateWithMailbox,
remoteUpdateWithoutMailbox, ownProperties);
expectCheckPluginState(ACTIVE);
expectCreateClientForOwnMailbox();
expectAssignContactToOwnMailboxForUpload();
expectAssignContactToOwnMailboxForDownload();
manager.startService();
// When the contact pairs a mailbox, the manager should create a client
// for the contact's mailbox and reassign the contact to the contact's
// mailbox for upload.
expectCreateClientForContactMailbox();
expectDeassignContactFromOwnMailboxForUpload();
expectAssignContactToContactMailboxForUpload(remoteProperties);
manager.eventOccurred(new RemoteMailboxUpdateEvent(contact.getId(),
remoteUpdateWithMailbox));
// At shutdown the manager should destroy the client for the contact's
// mailbox, the client for our own mailbox, and the reachability
// monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForContactMailbox();
expectDestroyClientForOwnMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testReassignsContactForUploadWhenContactUnpairsMailbox()
throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We have a mailbox and so does the
// contact.
//
// We're online, so the manager should create clients for the
// contact's mailbox and our mailbox. The manager should assign the
// contact to the contact's mailbox for upload and our mailbox for
// download.
expectLoadUpdates(localUpdateWithMailbox,
remoteUpdateWithMailbox, ownProperties);
expectCheckPluginState(ACTIVE);
expectCreateClientForContactMailbox();
expectAssignContactToContactMailboxForUpload(remoteProperties);
expectCreateClientForOwnMailbox();
expectAssignContactToOwnMailboxForDownload();
manager.startService();
// When the contact unpairs their mailbox, the manager should destroy
// the client for the contact's mailbox and reassign the contact to
// our mailbox for upload.
expectDestroyClientForContactMailbox();
expectAssignContactToOwnMailboxForUpload();
manager.eventOccurred(new RemoteMailboxUpdateEvent(contact.getId(),
remoteUpdateWithoutMailbox));
// At shutdown the manager should destroy the client for our mailbox
// and the reachability monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForOwnMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testReassignsContactForUploadWhenContactReplacesMailbox()
throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We have a mailbox and so does the
// contact.
//
// We're online, so the manager should create clients for the
// contact's mailbox and our mailbox. The manager should assign the
// contact to the contact's mailbox for upload and our mailbox for
// download.
expectLoadUpdates(localUpdateWithMailbox,
remoteUpdateWithMailbox, ownProperties);
expectCheckPluginState(ACTIVE);
expectCreateClientForContactMailbox();
expectAssignContactToContactMailboxForUpload(remoteProperties);
expectCreateClientForOwnMailbox();
expectAssignContactToOwnMailboxForDownload();
manager.startService();
// When the contact replaces their mailbox, the manager should replace
// the client for the contact's mailbox and assign the contact to
// the contact's new mailbox for upload.
expectDestroyClientForContactMailbox();
expectCreateClientForContactMailbox();
expectAssignContactToContactMailboxForUpload(
remotePropertiesForNewMailbox);
manager.eventOccurred(new RemoteMailboxUpdateEvent(contact.getId(),
remoteUpdateWithNewMailbox));
// At shutdown the manager should destroy the client for the contact's
// mailbox, the client for our own mailbox, and the reachability
// monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForContactMailbox();
expectDestroyClientForOwnMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testReassignsContactWhenContactReplacesMailbox()
throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We don't have a mailbox but the
// contact does.
//
// We're online, so the manager should create a client for the
// contact's mailbox and assign the contact to the contact's mailbox
// for upload and download.
expectLoadUpdates(localUpdateWithoutMailbox,
remoteUpdateWithMailbox, null);
expectCheckPluginState(ACTIVE);
expectCreateClientForContactMailbox();
expectAssignContactToContactMailboxForUpload(remoteProperties);
expectAssignContactToContactMailboxForDownload(remoteProperties);
manager.startService();
// When the contact replaces their mailbox, the manager should replace
// the client for the contact's mailbox and assign the contact to
// the contact's new mailbox for upload and download.
expectDestroyClientForContactMailbox();
expectCreateClientForContactMailbox();
expectAssignContactToContactMailboxForUpload(
remotePropertiesForNewMailbox);
expectAssignContactToContactMailboxForDownload(
remotePropertiesForNewMailbox);
manager.eventOccurred(new RemoteMailboxUpdateEvent(contact.getId(),
remoteUpdateWithNewMailbox));
// At shutdown the manager should destroy the client for the contact's
// mailbox and the reachability monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForContactMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testDoesNotReassignContactWhenRemotePropertiesAreUnchanged()
throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We don't have a mailbox but the
// contact does.
//
// We're online, so the manager should create a client for the
// contact's mailbox and assign the contact to the contact's mailbox
// for upload and download.
expectLoadUpdates(localUpdateWithoutMailbox,
remoteUpdateWithMailbox, null);
expectCheckPluginState(ACTIVE);
expectCreateClientForContactMailbox();
expectAssignContactToContactMailboxForUpload(remoteProperties);
expectAssignContactToContactMailboxForDownload(remoteProperties);
manager.startService();
// When the contact sends an update with unchanged properties, the
// clients and assignments should not be affected.
manager.eventOccurred(new RemoteMailboxUpdateEvent(contact.getId(),
remoteUpdateWithMailbox));
// At shutdown the manager should destroy the client for the contact's
// mailbox and the reachability monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForContactMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testAssignsContactToOurMailboxWhenClientVersionsBecomeCompatible()
throws Exception {
// At startup the manager should load the local and remote updates
// and our own mailbox properties. We have a mailbox but the contact
// doesn't. The contact's client API versions are incompatible with
// our mailbox.
//
// We're online, so the manager should create a client for our own
// mailbox. The contact's client API versions are incompatible with
// our mailbox, so the contact should not be assigned to our mailbox.
expectLoadUpdates(localUpdateWithMailbox,
remoteUpdateWithIncompatibleClientVersions, ownProperties);
expectCheckPluginState(ACTIVE);
expectCreateClientForOwnMailbox();
manager.startService();
// When the contact sends an update indicating that their client API
// versions are now compatible with our mailbox, the manager should
// assign the contact to our mailbox for upload and download.
expectAssignContactToOwnMailboxForUpload();
expectAssignContactToOwnMailboxForDownload();
manager.eventOccurred(new RemoteMailboxUpdateEvent(contact.getId(),
remoteUpdateWithoutMailbox));
// At shutdown the manager should destroy the client for our own
// mailbox and the reachability monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForOwnMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
@Test
public void testRecreatesClientsWhenOwnMailboxServerVersionsChange()
throws Exception {
long now = System.currentTimeMillis();
List<MailboxVersion> compatibleVersions =
new ArrayList<>(CLIENT_SUPPORTS);
compatibleVersions.add(new MailboxVersion(999, 0));
MailboxStatus mailboxStatus =
new MailboxStatus(now, now, 0, compatibleVersions);
// At startup the manager should load the local and remote updates
// and our own mailbox properties. The contact has a mailbox, so the
// remote update contains the properties received from the contact.
// We also have a mailbox, so the local update contains the properties
// we sent to the contact.
//
// We're online, so the manager should create clients for the
// contact's mailbox and our mailbox. The manager should assign the
// contact to the contact's mailbox for upload and our mailbox for
// download.
expectLoadUpdates(localUpdateWithMailbox,
remoteUpdateWithMailbox, ownProperties);
expectCheckPluginState(ACTIVE);
expectCreateClientForContactMailbox();
expectAssignContactToContactMailboxForUpload(remoteProperties);
expectCreateClientForOwnMailbox();
expectAssignContactToOwnMailboxForDownload();
manager.startService();
// When we learn that our mailbox's API versions have changed, the
// manager should destroy and recreate the clients for our own mailbox
// and the contact's mailbox and assign the contact to the new clients.
expectDestroyClientForContactMailbox();
expectDestroyClientForOwnMailbox();
expectCreateClientForContactMailbox();
expectAssignContactToContactMailboxForUpload(remoteProperties);
expectCreateClientForOwnMailbox();
expectAssignContactToOwnMailboxForDownload();
manager.eventOccurred(
new OwnMailboxConnectionStatusEvent(mailboxStatus));
// At shutdown the manager should destroy the client for the contact's
// mailbox, the client for our own mailbox, and the reachability
// monitor.
expectRunTaskOnEventExecutor();
expectDestroyClientForContactMailbox();
expectDestroyClientForOwnMailbox();
expectDestroyReachabilityMonitor();
manager.stopService();
}
private void expectLoadUpdates(MailboxUpdate local,
@Nullable MailboxUpdate remote,
@Nullable MailboxProperties own) throws Exception {
Transaction txn = new Transaction(null, true);
context.checking(new DbExpectations() {{
oneOf(reachabilityMonitor).start();
oneOf(dbExecutor).execute(with(any(Runnable.class)));
will(new RunAction());
oneOf(db).transaction(with(true), withDbRunnable(txn));
oneOf(contactManager).getContacts(txn);
will(returnValue(singletonList(contact)));
oneOf(mailboxUpdateManager).getLocalUpdate(txn, contact.getId());
will(returnValue(local));
oneOf(mailboxUpdateManager).getRemoteUpdate(txn, contact.getId());
will(returnValue(remote));
oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn);
will(returnValue(own));
}});
}
private void expectCheckPluginState(State state) {
context.checking(new Expectations() {{
oneOf(pluginManager).getPlugin(ID);
will(returnValue(plugin));
oneOf(plugin).getState();
will(returnValue(state));
}});
}
private void expectCreateClientForOwnMailbox() {
context.checking(new Expectations() {{
oneOf(mailboxClientFactory).createOwnMailboxClient(
reachabilityMonitor, ownProperties);
will(returnValue(ownClient));
oneOf(ownClient).start();
}});
}
private void expectCreateClientForContactMailbox() {
context.checking(new Expectations() {{
oneOf(mailboxClientFactory)
.createContactMailboxClient(reachabilityMonitor);
will(returnValue(contactClient));
oneOf(contactClient).start();
}});
}
private void expectAssignContactToOwnMailboxForDownload() {
context.checking(new Expectations() {{
oneOf(ownClient).assignContactForDownload(contact.getId(),
ownProperties,
requireNonNull(localProperties.getOutboxId()));
}});
}
private void expectAssignContactToOwnMailboxForUpload() {
context.checking(new Expectations() {{
oneOf(ownClient).assignContactForUpload(contact.getId(),
ownProperties,
requireNonNull(localProperties.getInboxId()));
}});
}
private void expectAssignContactToContactMailboxForDownload(
MailboxProperties remoteProperties) {
context.checking(new Expectations() {{
oneOf(contactClient).assignContactForDownload(contact.getId(),
remoteProperties,
requireNonNull(remoteProperties.getInboxId()));
}});
}
private void expectAssignContactToContactMailboxForUpload(
MailboxProperties remoteProperties) {
context.checking(new Expectations() {{
oneOf(contactClient).assignContactForUpload(contact.getId(),
remoteProperties,
requireNonNull(remoteProperties.getOutboxId()));
}});
}
private void expectDeassignContactFromOwnMailboxForUpload() {
context.checking(new Expectations() {{
oneOf(ownClient).deassignContactForUpload(contact.getId());
}});
}
private void expectDeassignContactFromOwnMailboxForDownload() {
context.checking(new Expectations() {{
oneOf(ownClient).deassignContactForDownload(contact.getId());
}});
}
private void expectDeassignContactFromContactMailboxForDownload() {
context.checking(new Expectations() {{
oneOf(contactClient).deassignContactForDownload(contact.getId());
}});
}
private void expectRunTaskOnEventExecutor() {
context.checking(new Expectations() {{
oneOf(eventExecutor).execute(with(any(Runnable.class)));
will(new RunAction());
}});
}
private void expectDestroyClientForOwnMailbox() {
context.checking(new Expectations() {{
oneOf(ownClient).destroy();
}});
}
private void expectDestroyClientForContactMailbox() {
context.checking(new Expectations() {{
oneOf(contactClient).destroy();
}});
}
private void expectDestroyReachabilityMonitor() {
context.checking(new Expectations() {{
oneOf(reachabilityMonitor).destroy();
}});
}
}

View File

@@ -0,0 +1,18 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.bramble.test.BrambleIntegrationTestComponent;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = {
BrambleCoreIntegrationTestModule.class,
BrambleCoreModule.class
})
interface MailboxIntegrationTestComponent extends
BrambleIntegrationTestComponent {
}

View File

@@ -0,0 +1,80 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.BrambleCoreEagerSingletons;
import org.briarproject.bramble.api.WeakSingletonProvider;
import org.briarproject.bramble.api.mailbox.InvalidMailboxIdException;
import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
import org.briarproject.bramble.io.IoModule;
import javax.annotation.Nonnull;
import javax.inject.Singleton;
import javax.net.SocketFactory;
import dagger.Module;
import dagger.Provides;
import okhttp3.OkHttpClient;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
class MailboxIntegrationTestUtils {
static final String URL_BASE = "http://127.0.0.1:8000";
static final MailboxAuthToken SETUP_TOKEN;
static {
try {
SETUP_TOKEN = MailboxAuthToken.fromString(
"54686973206973206120736574757020746f6b656e20666f722042726961722e");
} catch (InvalidMailboxIdException e) {
throw new IllegalStateException();
}
}
static WeakSingletonProvider<OkHttpClient> createHttpClientProvider() {
OkHttpClient client = new OkHttpClient.Builder()
.socketFactory(SocketFactory.getDefault())
.connectTimeout(60_000, MILLISECONDS)
.build();
return new WeakSingletonProvider<OkHttpClient>() {
@Override
@Nonnull
public OkHttpClient createInstance() {
return client;
}
};
}
static MailboxApi createMailboxApi() {
return new MailboxApiImpl(createHttpClientProvider(), onion -> onion);
}
static MailboxIntegrationTestComponent createTestComponent() {
MailboxIntegrationTestComponent component =
DaggerMailboxIntegrationTestComponent
.builder()
.ioModule(new TestIoModule())
.mailboxModule(new TestMailboxModule())
.build();
BrambleCoreEagerSingletons.Helper.injectEagerSingletons(component);
return component;
}
@Module
static class TestIoModule extends IoModule {
@Provides
@Singleton
WeakSingletonProvider<OkHttpClient> provideOkHttpClientProvider() {
return createHttpClientProvider();
}
}
@Module
static class TestMailboxModule extends MailboxModule {
@Provides
UrlConverter provideUrlConverter() {
return onion -> onion;
}
}
}

View File

@@ -110,8 +110,7 @@ public class MailboxPairingTaskImplTest extends BrambleMockTestCase {
oneOf(db).transaction(with(false), withDbRunnable(txn));
oneOf(mailboxSettingsManager).setOwnMailboxProperties(
with(txn), with(matches(ownerProperties)));
oneOf(mailboxSettingsManager).recordSuccessfulConnection(txn, time,
ownerProperties.getServerSupports());
oneOf(mailboxSettingsManager).recordSuccessfulConnection(txn, time);
oneOf(db).getContacts(txn);
will(returnValue(singletonList(contact1)));
oneOf(mailboxUpdateManager).getRemoteUpdate(txn,

View File

@@ -5,7 +5,6 @@ import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager.MailboxHook;
import org.briarproject.bramble.api.mailbox.MailboxStatus;
import org.briarproject.bramble.api.mailbox.MailboxVersion;
import org.briarproject.bramble.api.mailbox.event.OwnMailboxConnectionStatusEvent;
@@ -19,6 +18,7 @@ import java.util.List;
import java.util.Random;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_KEY_ATTEMPTS;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_KEY_LAST_ATTEMPT;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_KEY_LAST_SUCCESS;
@@ -27,12 +27,10 @@ import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTIN
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_KEY_TOKEN;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_NAMESPACE;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_UPLOADS_NAMESPACE;
import static org.briarproject.bramble.test.TestUtils.getEvent;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.test.TestUtils.hasEvent;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -41,7 +39,6 @@ public class MailboxSettingsManagerImplTest extends BrambleMockTestCase {
private final SettingsManager settingsManager =
context.mock(SettingsManager.class);
private final MailboxHook hook = context.mock(MailboxHook.class);
private final MailboxSettingsManager manager =
new MailboxSettingsManagerImpl(settingsManager);
@@ -50,10 +47,7 @@ public class MailboxSettingsManagerImplTest extends BrambleMockTestCase {
private final MailboxAuthToken token = new MailboxAuthToken(getRandomId());
private final List<MailboxVersion> serverSupports =
asList(new MailboxVersion(1, 0), new MailboxVersion(1, 1));
private final MailboxProperties properties = new MailboxProperties(onion,
token, serverSupports);
private final int[] serverSupportsInts = {1, 0, 1, 1};
private final Settings pairedSettings;
private final ContactId contactId1 = new ContactId(random.nextInt());
private final ContactId contactId2 = new ContactId(random.nextInt());
private final ContactId contactId3 = new ContactId(random.nextInt());
@@ -62,14 +56,6 @@ public class MailboxSettingsManagerImplTest extends BrambleMockTestCase {
private final long lastSuccess = now - 2345;
private final int attempts = 123;
public MailboxSettingsManagerImplTest() {
pairedSettings = new Settings();
pairedSettings.put(SETTINGS_KEY_ONION, onion);
pairedSettings.put(SETTINGS_KEY_TOKEN, token.toString());
pairedSettings.putIntArray(SETTINGS_KEY_SERVER_SUPPORTS,
serverSupportsInts);
}
@Test
public void testReturnsNullPropertiesIfSettingsAreEmpty() throws Exception {
Transaction txn = new Transaction(null, true);
@@ -86,10 +72,14 @@ public class MailboxSettingsManagerImplTest extends BrambleMockTestCase {
@Test
public void testReturnsProperties() throws Exception {
Transaction txn = new Transaction(null, true);
Settings settings = new Settings();
settings.put(SETTINGS_KEY_ONION, onion);
settings.put(SETTINGS_KEY_TOKEN, token.toString());
settings.putIntArray(SETTINGS_KEY_SERVER_SUPPORTS, serverSupportsInts);
context.checking(new Expectations() {{
oneOf(settingsManager).getSettings(txn, SETTINGS_NAMESPACE);
will(returnValue(pairedSettings));
will(returnValue(settings));
}});
MailboxProperties properties = manager.getOwnMailboxProperties(txn);
@@ -103,38 +93,20 @@ public class MailboxSettingsManagerImplTest extends BrambleMockTestCase {
@Test
public void testStoresProperties() throws Exception {
Transaction txn = new Transaction(null, false);
manager.registerMailboxHook(hook);
context.checking(new Expectations() {{
oneOf(settingsManager).mergeSettings(txn, pairedSettings,
SETTINGS_NAMESPACE);
oneOf(hook).mailboxPaired(txn, properties);
}});
manager.setOwnMailboxProperties(txn, properties);
}
@Test
public void testRemovesProperties() throws Exception {
Transaction txn = new Transaction(null, false);
Settings expectedSettings = new Settings();
expectedSettings.put(SETTINGS_KEY_ONION, "");
expectedSettings.put(SETTINGS_KEY_TOKEN, "");
expectedSettings.put(SETTINGS_KEY_ATTEMPTS, "");
expectedSettings.put(SETTINGS_KEY_LAST_ATTEMPT, "");
expectedSettings.put(SETTINGS_KEY_LAST_SUCCESS, "");
expectedSettings.put(SETTINGS_KEY_SERVER_SUPPORTS, "");
manager.registerMailboxHook(hook);
expectedSettings.put(SETTINGS_KEY_ONION, onion);
expectedSettings.put(SETTINGS_KEY_TOKEN, token.toString());
expectedSettings.putIntArray(SETTINGS_KEY_SERVER_SUPPORTS,
serverSupportsInts);
MailboxProperties properties = new MailboxProperties(onion, token,
serverSupports);
context.checking(new Expectations() {{
oneOf(settingsManager).mergeSettings(txn, expectedSettings,
SETTINGS_NAMESPACE);
oneOf(hook).mailboxUnpaired(txn);
}});
manager.removeOwnMailboxProperties(txn);
manager.setOwnMailboxProperties(txn, properties);
}
@Test
@@ -175,60 +147,63 @@ public class MailboxSettingsManagerImplTest extends BrambleMockTestCase {
@Test
public void testRecordsSuccess() throws Exception {
Transaction txn = new Transaction(null, false);
Settings oldSettings = new Settings();
oldSettings
.putIntArray(SETTINGS_KEY_SERVER_SUPPORTS, serverSupportsInts);
Settings expectedSettings = new Settings();
expectedSettings.putLong(SETTINGS_KEY_LAST_ATTEMPT, now);
expectedSettings.putLong(SETTINGS_KEY_LAST_SUCCESS, now);
expectedSettings.putInt(SETTINGS_KEY_ATTEMPTS, 0);
expectedSettings.putIntArray(SETTINGS_KEY_SERVER_SUPPORTS,
serverSupportsInts);
context.checking(new Expectations() {{
oneOf(settingsManager).getSettings(txn, SETTINGS_NAMESPACE);
will(returnValue(pairedSettings));
will(returnValue(oldSettings));
oneOf(settingsManager).mergeSettings(txn, expectedSettings,
SETTINGS_NAMESPACE);
}});
manager.recordSuccessfulConnection(txn, now, serverSupports);
OwnMailboxConnectionStatusEvent e =
getEvent(txn, OwnMailboxConnectionStatusEvent.class);
MailboxStatus status = e.getStatus();
assertEquals(now, status.getTimeOfLastAttempt());
assertEquals(now, status.getTimeOfLastSuccess());
assertEquals(0, status.getAttemptsSinceSuccess());
assertFalse(status.hasProblem(now));
manager.recordSuccessfulConnection(txn, now);
assertTrue(hasEvent(txn, OwnMailboxConnectionStatusEvent.class));
}
@Test
public void testDoesNotRecordSuccessIfNotPaired() throws Exception {
public void testRecordsSuccessWithVersions() throws Exception {
Transaction txn = new Transaction(null, false);
List<MailboxVersion> versions = singletonList(new MailboxVersion(2, 1));
Settings expectedSettings = new Settings();
expectedSettings.putLong(SETTINGS_KEY_LAST_ATTEMPT, now);
expectedSettings.putLong(SETTINGS_KEY_LAST_SUCCESS, now);
expectedSettings.putInt(SETTINGS_KEY_ATTEMPTS, 0);
expectedSettings.putInt(SETTINGS_KEY_SERVER_SUPPORTS, 0);
int[] newVersionsInts = {2, 1};
expectedSettings
.putIntArray(SETTINGS_KEY_SERVER_SUPPORTS, newVersionsInts);
context.checking(new Expectations() {{
oneOf(settingsManager).getSettings(txn, SETTINGS_NAMESPACE);
will(returnValue(new Settings()));
oneOf(settingsManager).mergeSettings(txn, expectedSettings,
SETTINGS_NAMESPACE);
}});
manager.recordSuccessfulConnection(txn, now, serverSupports);
assertFalse(hasEvent(txn, OwnMailboxConnectionStatusEvent.class));
manager.recordSuccessfulConnection(txn, now, versions);
hasEvent(txn, OwnMailboxConnectionStatusEvent.class);
}
@Test
public void testRecordsFailureOnFirstAttempt() throws Exception {
testRecordsFailure(pairedSettings, 0, 0);
testRecordsFailure(new Settings(), 0);
}
@Test
public void testRecordsFailureOnLaterAttempt() throws Exception {
Settings oldSettings = new Settings();
oldSettings.putAll(pairedSettings);
oldSettings.putLong(SETTINGS_KEY_LAST_ATTEMPT, lastAttempt);
oldSettings.putLong(SETTINGS_KEY_LAST_SUCCESS, lastSuccess);
oldSettings.putInt(SETTINGS_KEY_ATTEMPTS, attempts);
testRecordsFailure(oldSettings, attempts, lastSuccess);
testRecordsFailure(oldSettings, attempts);
}
private void testRecordsFailure(Settings oldSettings, int oldAttempts,
long lastSuccess) throws Exception {
private void testRecordsFailure(Settings oldSettings, int oldAttempts)
throws Exception {
Transaction txn = new Transaction(null, false);
Settings expectedSettings = new Settings();
expectedSettings.putLong(SETTINGS_KEY_LAST_ATTEMPT, now);
@@ -242,25 +217,6 @@ public class MailboxSettingsManagerImplTest extends BrambleMockTestCase {
}});
manager.recordFailedConnectionAttempt(txn, now);
OwnMailboxConnectionStatusEvent e =
getEvent(txn, OwnMailboxConnectionStatusEvent.class);
MailboxStatus status = e.getStatus();
assertEquals(now, status.getTimeOfLastAttempt());
assertEquals(lastSuccess, status.getTimeOfLastSuccess());
assertEquals(oldAttempts + 1, status.getAttemptsSinceSuccess());
}
@Test
public void testDoesNotRecordFailureIfNotPaired() throws Exception {
Transaction txn = new Transaction(null, false);
context.checking(new Expectations() {{
oneOf(settingsManager).getSettings(txn, SETTINGS_NAMESPACE);
will(returnValue(new Settings()));
}});
manager.recordFailedConnectionAttempt(txn, now);
assertFalse(hasEvent(txn, OwnMailboxConnectionStatusEvent.class));
}
@Test

View File

@@ -3,7 +3,6 @@ package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.client.ContactGroupFactory;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfEntry;
@@ -17,9 +16,6 @@ import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import org.briarproject.bramble.api.mailbox.MailboxUpdate;
import org.briarproject.bramble.api.mailbox.MailboxUpdateWithMailbox;
import org.briarproject.bramble.api.mailbox.MailboxVersion;
import org.briarproject.bramble.api.mailbox.event.MailboxPairedEvent;
import org.briarproject.bramble.api.mailbox.event.MailboxUnpairedEvent;
import org.briarproject.bramble.api.mailbox.event.MailboxUpdateSentToNewContactEvent;
import org.briarproject.bramble.api.mailbox.event.RemoteMailboxUpdateEvent;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId;
@@ -36,12 +32,9 @@ import java.util.List;
import java.util.Map;
import java.util.Random;
import static java.util.Collections.singleton;
import static java.util.Collections.singletonList;
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.CLIENT_ID;
import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.GROUP_KEY_SENT_CLIENT_SUPPORTS;
import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.GROUP_KEY_SENT_SERVER_SUPPORTS;
import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.MAJOR_VERSION;
import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.MSG_KEY_LOCAL;
import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.MSG_KEY_VERSION;
@@ -52,7 +45,6 @@ import static org.briarproject.bramble.api.mailbox.MailboxUpdateManager.PROP_KEY
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.api.sync.validation.IncomingMessageHook.DeliveryAction.ACCEPT_DO_NOT_SHARE;
import static org.briarproject.bramble.test.TestUtils.getContact;
import static org.briarproject.bramble.test.TestUtils.getEvent;
import static org.briarproject.bramble.test.TestUtils.getGroup;
import static org.briarproject.bramble.test.TestUtils.getMailboxProperties;
import static org.briarproject.bramble.test.TestUtils.getMessage;
@@ -79,11 +71,6 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
private final MailboxSettingsManager mailboxSettingsManager =
context.mock(MailboxSettingsManager.class);
private final Contact contact = getContact();
private final List<Contact> contacts = singletonList(contact);
private final Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
private final GroupId contactGroupId = contactGroup.getId();
private final Message message = getMessage(contactGroupId);
private final Group localGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
private final BdfDictionary propsDict;
private final BdfDictionary emptyPropsDict = new BdfDictionary();
@@ -93,8 +80,6 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
private final BdfList newerClientSupports;
private final List<MailboxVersion> someServerSupportsList;
private final BdfList someServerSupports;
private final List<MailboxVersion> newerServerSupportsList;
private final BdfList newerServerSupports;
private final BdfList emptyServerSupports = new BdfList();
private final MailboxProperties updateProps;
private final MailboxUpdateWithMailbox updateWithMailbox;
@@ -120,12 +105,6 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
someServerSupports = BdfList.of(BdfList.of(
someServerSupportsList.get(0).getMajor(),
someServerSupportsList.get(0).getMinor()));
newerServerSupportsList = singletonList(new MailboxVersion(
someServerSupportsList.get(0).getMajor(),
someServerSupportsList.get(0).getMinor() + 1));
newerServerSupports = BdfList.of(BdfList.of(
newerServerSupportsList.get(0).getMajor(),
newerServerSupportsList.get(0).getMinor()));
updateNoMailbox = new MailboxUpdate(someClientSupportsList);
@@ -156,6 +135,8 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
@Test
public void testCreatesGroupsAtUnpairedStartup() throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact();
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>();
BdfDictionary sentDict = BdfDictionary.of(new BdfEntry(
GROUP_KEY_SENT_CLIENT_SUPPORTS,
@@ -177,8 +158,8 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
contact.getId(), CLIENT_ID, MAJOR_VERSION);
will(returnValue(SHARED));
oneOf(db).setGroupVisibility(txn, contact.getId(),
contactGroupId, SHARED);
oneOf(clientHelper).setContactId(txn, contactGroupId,
contactGroup.getId(), SHARED);
oneOf(clientHelper).setContactId(txn, contactGroup.getId(),
contact.getId());
oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn);
will(returnValue(null));
@@ -186,9 +167,9 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroupId);
contactGroup.getId());
will(returnValue(messageMetadata));
expectStoreMessage(txn, contactGroupId, 1, someClientSupports,
expectStoreMessage(txn, contactGroup.getId(), 1, someClientSupports,
emptyServerSupports, emptyPropsDict);
oneOf(clientHelper).mergeGroupMetadata(txn, localGroup.getId(),
@@ -197,14 +178,14 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.onDatabaseOpened(txn);
assertFalse(hasEvent(txn, MailboxUpdateSentToNewContactEvent.class));
}
@Test
public void testCreatesGroupsAndCreatesAndSendsAtPairedStartup()
throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact();
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>();
BdfDictionary sentDict = BdfDictionary.of(new BdfEntry(
GROUP_KEY_SENT_CLIENT_SUPPORTS,
@@ -226,8 +207,8 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
contact.getId(), CLIENT_ID, MAJOR_VERSION);
will(returnValue(SHARED));
oneOf(db).setGroupVisibility(txn, contact.getId(),
contactGroupId, SHARED);
oneOf(clientHelper).setContactId(txn, contactGroupId,
contactGroup.getId(), SHARED);
oneOf(clientHelper).setContactId(txn, contactGroup.getId(),
contact.getId());
oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn);
will(returnValue(ownProps));
@@ -241,9 +222,9 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroupId);
contactGroup.getId());
will(returnValue(messageMetadata));
expectStoreMessage(txn, contactGroupId, 1, someClientSupports,
expectStoreMessage(txn, contactGroup.getId(), 1, someClientSupports,
someServerSupports, propsDict);
oneOf(clientHelper).mergeGroupMetadata(txn, localGroup.getId(),
@@ -252,14 +233,14 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.onDatabaseOpened(txn);
assertFalse(hasEvent(txn, MailboxUpdateSentToNewContactEvent.class));
}
@Test
public void testUnchangedClientSupportsOnSecondStartup() throws Exception {
Transaction txn1 = new Transaction(null, false);
Transaction txn2 = new Transaction(null, false);
Transaction txn = new Transaction(null, false);
Contact contact = getContact();
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
Map<MessageId, BdfDictionary> emptyMessageMetadata =
new LinkedHashMap<>();
@@ -268,48 +249,46 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
someClientSupports));
context.checking(new Expectations() {{
oneOf(db).containsGroup(txn1, localGroup.getId());
oneOf(db).containsGroup(txn, localGroup.getId());
will(returnValue(false));
oneOf(db).addGroup(txn1, localGroup);
oneOf(db).getContacts(txn1);
oneOf(db).addGroup(txn, localGroup);
oneOf(db).getContacts(txn);
will(returnValue(singletonList(contact)));
// addingContact()
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(db).addGroup(txn1, contactGroup);
oneOf(clientVersioningManager).getClientVisibility(txn1,
oneOf(db).addGroup(txn, contactGroup);
oneOf(clientVersioningManager).getClientVisibility(txn,
contact.getId(), CLIENT_ID, MAJOR_VERSION);
will(returnValue(SHARED));
oneOf(db).setGroupVisibility(txn1, contact.getId(),
contactGroupId, SHARED);
oneOf(clientHelper).setContactId(txn1, contactGroupId,
oneOf(db).setGroupVisibility(txn, contact.getId(),
contactGroup.getId(), SHARED);
oneOf(clientHelper).setContactId(txn, contactGroup.getId(),
contact.getId());
oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn1);
oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn);
will(returnValue(null));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn1,
contactGroupId);
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId());
will(returnValue(emptyMessageMetadata));
expectStoreMessage(txn1, contactGroupId, 1, someClientSupports,
expectStoreMessage(txn, contactGroup.getId(), 1, someClientSupports,
emptyServerSupports, emptyPropsDict);
oneOf(clientHelper).mergeGroupMetadata(txn1, localGroup.getId(),
oneOf(clientHelper).mergeGroupMetadata(txn, localGroup.getId(),
sentDict);
}});
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.onDatabaseOpened(txn1);
assertFalse(hasEvent(txn1, MailboxUpdateSentToNewContactEvent.class));
t.onDatabaseOpened(txn);
context.checking(new Expectations() {{
oneOf(db).containsGroup(txn2, localGroup.getId());
oneOf(db).containsGroup(txn, localGroup.getId());
will(returnValue(true));
oneOf(clientHelper).getGroupMetadataAsDictionary(txn2,
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(sentDict));
oneOf(clientHelper).parseMailboxVersionList(someClientSupports);
@@ -317,16 +296,16 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
}});
t = createInstance(someClientSupportsList);
t.onDatabaseOpened(txn2);
assertFalse(hasEvent(txn2, MailboxUpdateSentToNewContactEvent.class));
t.onDatabaseOpened(txn);
}
@Test
public void testSendsUpdateWhenClientSupportsChangedOnSecondStartup()
throws Exception {
Transaction txn1 = new Transaction(null, false);
Transaction txn2 = new Transaction(null, false);
Transaction txn = new Transaction(null, false);
Contact contact = getContact();
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
Map<MessageId, BdfDictionary> emptyMessageMetadata =
new LinkedHashMap<>();
@@ -335,43 +314,41 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
someClientSupports));
context.checking(new Expectations() {{
oneOf(db).containsGroup(txn1, localGroup.getId());
oneOf(db).containsGroup(txn, localGroup.getId());
will(returnValue(false));
oneOf(db).addGroup(txn1, localGroup);
oneOf(db).getContacts(txn1);
oneOf(db).addGroup(txn, localGroup);
oneOf(db).getContacts(txn);
will(returnValue(singletonList(contact)));
// addingContact()
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(db).addGroup(txn1, contactGroup);
oneOf(clientVersioningManager).getClientVisibility(txn1,
oneOf(db).addGroup(txn, contactGroup);
oneOf(clientVersioningManager).getClientVisibility(txn,
contact.getId(), CLIENT_ID, MAJOR_VERSION);
will(returnValue(SHARED));
oneOf(db).setGroupVisibility(txn1, contact.getId(),
contactGroupId, SHARED);
oneOf(clientHelper).setContactId(txn1, contactGroupId,
oneOf(db).setGroupVisibility(txn, contact.getId(),
contactGroup.getId(), SHARED);
oneOf(clientHelper).setContactId(txn, contactGroup.getId(),
contact.getId());
oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn1);
oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn);
will(returnValue(null));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn1,
contactGroupId);
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId());
will(returnValue(emptyMessageMetadata));
expectStoreMessage(txn1, contactGroupId, 1, someClientSupports,
expectStoreMessage(txn, contactGroup.getId(), 1, someClientSupports,
emptyServerSupports, emptyPropsDict);
oneOf(clientHelper).mergeGroupMetadata(txn1, localGroup.getId(),
oneOf(clientHelper).mergeGroupMetadata(txn, localGroup.getId(),
sentDict);
}});
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.onDatabaseOpened(txn1);
assertFalse(hasEvent(txn1, MailboxUpdateSentToNewContactEvent.class));
t.onDatabaseOpened(txn);
BdfDictionary metaDictionary = BdfDictionary.of(
new BdfEntry(MSG_KEY_VERSION, 1),
@@ -380,66 +357,66 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>();
MessageId messageId = new MessageId(getRandomId());
messageMetadata.put(messageId, metaDictionary);
BdfList oldBody = BdfList.of(1, someClientSupports, emptyServerSupports,
emptyPropsDict);
BdfList body = BdfList.of(1, someClientSupports, someServerSupports,
propsDict);
BdfDictionary newerSentDict = BdfDictionary.of(new BdfEntry(
GROUP_KEY_SENT_CLIENT_SUPPORTS,
newerClientSupports));
context.checking(new Expectations() {{
oneOf(db).containsGroup(txn2, localGroup.getId());
oneOf(db).containsGroup(txn, localGroup.getId());
will(returnValue(true));
// Find out that we are now on newerClientSupportsList
oneOf(clientHelper).getGroupMetadataAsDictionary(txn2,
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(sentDict));
oneOf(clientHelper).parseMailboxVersionList(someClientSupports);
will(returnValue(someClientSupportsList));
oneOf(db).getContacts(txn2);
oneOf(db).getContacts(txn);
will(returnValue(singletonList(contact)));
oneOf(db).getContact(txn2, contact.getId());
oneOf(db).getContact(txn, contact.getId());
will(returnValue(contact));
// getLocalUpdate()
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn2,
contactGroupId);
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId());
will(returnValue(messageMetadata));
oneOf(clientHelper).getMessageAsList(txn2, messageId);
will(returnValue(oldBody));
oneOf(clientHelper).getMessageAsList(txn, messageId);
will(returnValue(body));
oneOf(clientHelper).parseAndValidateMailboxUpdate(
someClientSupports, emptyServerSupports, emptyPropsDict);
will(returnValue(updateNoMailbox));
someClientSupports, someServerSupports, propsDict);
will(returnValue(updateWithMailbox));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
// storeMessageReplaceLatest()
oneOf(clientHelper).getMessageMetadataAsDictionary(txn2,
contactGroupId);
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId());
will(returnValue(messageMetadata));
expectStoreMessage(txn2, contactGroupId, 2,
newerClientSupports, emptyServerSupports, emptyPropsDict);
oneOf(db).removeMessage(txn2, messageId);
expectStoreMessage(txn, contactGroup.getId(), 2,
newerClientSupports, someServerSupports, propsDict);
oneOf(db).removeMessage(txn, messageId);
oneOf(clientHelper).mergeGroupMetadata(txn2, localGroup.getId(),
oneOf(clientHelper).mergeGroupMetadata(txn, localGroup.getId(),
newerSentDict);
}});
t = createInstance(newerClientSupportsList);
t.onDatabaseOpened(txn2);
assertFalse(hasEvent(txn2, MailboxUpdateSentToNewContactEvent.class));
t.onDatabaseOpened(txn);
}
@Test
public void testCreatesContactGroupWhenAddingContactUnpaired()
throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact();
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>();
context.checking(new Expectations() {{
@@ -452,8 +429,8 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
contact.getId(), CLIENT_ID, MAJOR_VERSION);
will(returnValue(SHARED));
oneOf(db).setGroupVisibility(txn, contact.getId(),
contactGroupId, SHARED);
oneOf(clientHelper).setContactId(txn, contactGroupId,
contactGroup.getId(), SHARED);
oneOf(clientHelper).setContactId(txn, contactGroup.getId(),
contact.getId());
oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn);
will(returnValue(null));
@@ -461,24 +438,22 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroupId);
contactGroup.getId());
will(returnValue(messageMetadata));
expectStoreMessage(txn, contactGroupId, 1, someClientSupports,
expectStoreMessage(txn, contactGroup.getId(), 1, someClientSupports,
emptyServerSupports, emptyPropsDict);
}});
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.addingContact(txn, contact);
MailboxUpdateSentToNewContactEvent
e = getEvent(txn, MailboxUpdateSentToNewContactEvent.class);
assertNoMailboxPropertiesSent(e, someClientSupportsList);
}
@Test
public void testCreatesContactGroupAndCreatesAndSendsWhenAddingContactPaired()
throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact();
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>();
context.checking(new Expectations() {{
@@ -491,8 +466,8 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
contact.getId(), CLIENT_ID, MAJOR_VERSION);
will(returnValue(SHARED));
oneOf(db).setGroupVisibility(txn, contact.getId(),
contactGroupId, SHARED);
oneOf(clientHelper).setContactId(txn, contactGroupId,
contactGroup.getId(), SHARED);
oneOf(clientHelper).setContactId(txn, contactGroup.getId(),
contact.getId());
oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn);
will(returnValue(ownProps));
@@ -506,23 +481,21 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroupId);
contactGroup.getId());
will(returnValue(messageMetadata));
expectStoreMessage(txn, contactGroupId, 1, someClientSupports,
expectStoreMessage(txn, contactGroup.getId(), 1, someClientSupports,
someServerSupports, propsDict);
}});
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.addingContact(txn, contact);
MailboxUpdateSentToNewContactEvent
e = getEvent(txn, MailboxUpdateSentToNewContactEvent.class);
assertMailboxPropertiesSent(e, someClientSupportsList);
}
@Test
public void testRemovesGroupWhenRemovingContact() throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact();
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
context.checking(new Expectations() {{
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
@@ -539,6 +512,9 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
public void testDoesNotDeleteAnythingWhenFirstUpdateIsDelivered()
throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact();
GroupId contactGroupId = new GroupId(getRandomId());
Message message = getMessage(contactGroupId);
BdfList body = BdfList.of(1, someClientSupports, someServerSupports,
propsDict);
Metadata meta = new Metadata();
@@ -573,23 +549,16 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
assertEquals(ACCEPT_DO_NOT_SHARE,
t.incomingMessage(txn, message, meta));
RemoteMailboxUpdateEvent e =
getEvent(txn, RemoteMailboxUpdateEvent.class);
assertEquals(contact.getId(), e.getContact());
MailboxUpdate u = e.getMailboxUpdate();
assertTrue(u.hasMailbox());
MailboxUpdateWithMailbox uMailbox = (MailboxUpdateWithMailbox) u;
assertEquals(updateWithMailbox.getClientSupports(),
uMailbox.getClientSupports());
assertEquals(updateWithMailbox.getMailboxProperties(),
uMailbox.getMailboxProperties());
assertTrue(hasEvent(txn, RemoteMailboxUpdateEvent.class));
}
@Test
public void testDeletesOlderUpdateWhenUpdateIsDelivered()
throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact();
GroupId contactGroupId = new GroupId(getRandomId());
Message message = getMessage(contactGroupId);
BdfList body = BdfList.of(1, someClientSupports, someServerSupports,
propsDict);
Metadata meta = new Metadata();
@@ -632,22 +601,14 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
assertEquals(ACCEPT_DO_NOT_SHARE,
t.incomingMessage(txn, message, meta));
RemoteMailboxUpdateEvent e =
getEvent(txn, RemoteMailboxUpdateEvent.class);
assertEquals(contact.getId(), e.getContact());
MailboxUpdate u = e.getMailboxUpdate();
assertTrue(u.hasMailbox());
MailboxUpdateWithMailbox uMailbox = (MailboxUpdateWithMailbox) u;
assertEquals(updateWithMailbox.getClientSupports(),
uMailbox.getClientSupports());
assertEquals(updateWithMailbox.getMailboxProperties(),
uMailbox.getMailboxProperties());
assertTrue(hasEvent(txn, RemoteMailboxUpdateEvent.class));
}
@Test
public void testDeletesObsoleteUpdateWhenDelivered() throws Exception {
Transaction txn = new Transaction(null, false);
GroupId contactGroupId = new GroupId(getRandomId());
Message message = getMessage(contactGroupId);
Metadata meta = new Metadata();
BdfDictionary metaDictionary = BdfDictionary.of(
new BdfEntry(MSG_KEY_VERSION, 3),
@@ -674,13 +635,16 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
assertEquals(ACCEPT_DO_NOT_SHARE,
t.incomingMessage(txn, message, meta));
assertFalse(hasEvent(txn, RemoteMailboxUpdateEvent.class));
}
@Test
public void testCreatesAndStoresLocalUpdateWithNewVersionOnPairing()
throws Exception {
Contact contact = getContact();
List<Contact> contacts = singletonList(contact);
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
Transaction txn = new Transaction(null, false);
Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>();
MessageId latestId = new MessageId(getRandomId());
@@ -693,55 +657,37 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
new BdfEntry(MSG_KEY_VERSION, 3),
new BdfEntry(MSG_KEY_LOCAL, false)
));
BdfDictionary groupMetadata = new BdfDictionary();
groupMetadata.put(GROUP_KEY_SENT_SERVER_SUPPORTS, someServerSupports);
context.checking(new Expectations() {{
oneOf(db).getContacts(txn);
will(returnValue(contacts));
// Generate mailbox properties for contact
oneOf(crypto).generateUniqueId();
will(returnValue(updateProps.getAuthToken()));
oneOf(crypto).generateUniqueId();
will(returnValue(updateProps.getInboxId()));
oneOf(crypto).generateUniqueId();
will(returnValue(updateProps.getOutboxId()));
// Find latest update
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroupId);
contactGroup.getId());
will(returnValue(messageMetadata));
// Replace latest update with new update
expectStoreMessage(txn, contactGroupId, 2, someClientSupports,
expectStoreMessage(txn, contactGroup.getId(), 2, someClientSupports,
someServerSupports, propsDict);
oneOf(db).removeMessage(txn, latestId);
// Store sent server-supported versions
oneOf(clientHelper).mergeGroupMetadata(txn, localGroup.getId(),
groupMetadata);
}});
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.mailboxPaired(txn, ownProps);
MailboxPairedEvent e = getEvent(txn, MailboxPairedEvent.class);
assertEquals(ownProps, e.getProperties());
Map<ContactId, MailboxUpdateWithMailbox> localUpdates =
e.getLocalUpdates();
assertEquals(singleton(contact.getId()), localUpdates.keySet());
MailboxUpdateWithMailbox u = localUpdates.get(contact.getId());
assertEquals(updateWithMailbox.getClientSupports(),
u.getClientSupports());
assertEquals(updateWithMailbox.getMailboxProperties(),
u.getMailboxProperties());
assertFalse(hasEvent(txn, MailboxUpdateSentToNewContactEvent.class));
t.mailboxPaired(txn, ownProps.getOnion(), someServerSupportsList);
}
@Test
public void testStoresLocalUpdateNoMailboxWithNewVersionOnUnpairing()
throws Exception {
Contact contact = getContact();
List<Contact> contacts = singletonList(contact);
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
Transaction txn = new Transaction(null, false);
Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>();
@@ -755,117 +701,30 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
new BdfEntry(MSG_KEY_VERSION, 3),
new BdfEntry(MSG_KEY_LOCAL, false)
));
BdfDictionary groupMetadata = new BdfDictionary();
groupMetadata.put(GROUP_KEY_SENT_SERVER_SUPPORTS, NULL_VALUE);
context.checking(new Expectations() {{
oneOf(db).getContacts(txn);
will(returnValue(contacts));
// Find latest update
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroupId);
contactGroup.getId());
will(returnValue(messageMetadata));
// Replace latest update with new update
expectStoreMessage(txn, contactGroupId, 2, someClientSupports,
expectStoreMessage(txn, contactGroup.getId(), 2, someClientSupports,
emptyServerSupports, emptyPropsDict);
oneOf(db).removeMessage(txn, latestId);
// Remove sent server-supported versions
oneOf(clientHelper).mergeGroupMetadata(txn, localGroup.getId(),
groupMetadata);
}});
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.mailboxUnpaired(txn);
MailboxUnpairedEvent e = getEvent(txn, MailboxUnpairedEvent.class);
Map<ContactId, MailboxUpdate> localUpdates = e.getLocalUpdates();
assertEquals(singleton(contact.getId()), localUpdates.keySet());
MailboxUpdate u = localUpdates.get(contact.getId());
assertFalse(u.hasMailbox());
assertFalse(hasEvent(txn, MailboxUpdateSentToNewContactEvent.class));
}
@Test
public void testStoresLocalUpdateWhenServerSupportsChange()
throws Exception {
Transaction txn = new Transaction(null, false);
Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>();
MessageId latestId = new MessageId(getRandomId());
messageMetadata.put(latestId, BdfDictionary.of(
new BdfEntry(MSG_KEY_VERSION, 1),
new BdfEntry(MSG_KEY_LOCAL, true)
));
BdfList body = BdfList.of(1, someClientSupports, someServerSupports,
propsDict);
BdfDictionary oldGroupMetadata = new BdfDictionary();
oldGroupMetadata.put(GROUP_KEY_SENT_SERVER_SUPPORTS,
someServerSupports);
BdfDictionary newGroupMetadata = new BdfDictionary();
newGroupMetadata.put(GROUP_KEY_SENT_SERVER_SUPPORTS,
newerServerSupports);
context.checking(new Expectations() {{
// Load sent server-supported versions
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(oldGroupMetadata));
oneOf(clientHelper).parseMailboxVersionList(someServerSupports);
will(returnValue(someServerSupportsList));
// Update sent server-supported versions
oneOf(clientHelper).mergeGroupMetadata(txn, localGroup.getId(),
newGroupMetadata);
oneOf(db).getContacts(txn);
will(returnValue(contacts));
// Find latest update
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroupId);
will(returnValue(messageMetadata));
// Load and parse latest update
oneOf(clientHelper).getMessageAsList(txn, latestId);
will(returnValue(body));
oneOf(clientHelper).parseAndValidateMailboxUpdate(
someClientSupports, someServerSupports, propsDict);
will(returnValue(updateWithMailbox));
// Replace latest update with new update
expectStoreMessage(txn, contactGroupId, 2, someClientSupports,
newerServerSupports, propsDict);
oneOf(db).removeMessage(txn, latestId);
}});
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.serverSupportedVersionsReceived(txn, newerServerSupportsList);
}
@Test
public void testDoesNotStoreLocalUpdateWhenServerSupportsAreUnchanged()
throws Exception {
Transaction txn = new Transaction(null, false);
BdfDictionary groupMetadata = new BdfDictionary();
groupMetadata.put(GROUP_KEY_SENT_SERVER_SUPPORTS, someServerSupports);
context.checking(new Expectations() {{
// Load sent server-supported versions
oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(groupMetadata));
oneOf(clientHelper).parseMailboxVersionList(someServerSupports);
will(returnValue(someServerSupportsList));
}});
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.serverSupportedVersionsReceived(txn, someServerSupportsList);
}
@Test
public void testGetRemoteUpdate() throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact();
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
BdfDictionary metaDictionary = BdfDictionary.of(
new BdfEntry(MSG_KEY_VERSION, 1),
new BdfEntry(MSG_KEY_LOCAL, false)
@@ -883,7 +742,7 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
.createContactGroup(CLIENT_ID, MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroupId);
contactGroup.getId());
will(returnValue(messageMetadata));
oneOf(clientHelper).getMessageAsList(txn, messageId);
will(returnValue(body));
@@ -901,6 +760,8 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
public void testGetRemoteUpdateReturnsNullBecauseNoUpdate()
throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact();
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
Map<MessageId, BdfDictionary> emptyMessageMetadata =
new LinkedHashMap<>();
@@ -911,7 +772,7 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroupId);
contactGroup.getId());
will(returnValue(emptyMessageMetadata));
}});
@@ -922,6 +783,8 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
@Test
public void testGetRemoteUpdateNoMailbox() throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact();
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
BdfDictionary metaDictionary = BdfDictionary.of(
new BdfEntry(MSG_KEY_VERSION, 1),
new BdfEntry(MSG_KEY_LOCAL, false)
@@ -939,7 +802,7 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroupId);
contactGroup.getId());
will(returnValue(messageMetadata));
oneOf(clientHelper).getMessageAsList(txn, messageId);
will(returnValue(body));
@@ -956,6 +819,8 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
@Test
public void testGetLocalUpdate() throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact();
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
BdfDictionary metaDictionary = BdfDictionary.of(
new BdfEntry(MSG_KEY_VERSION, 1),
new BdfEntry(MSG_KEY_LOCAL, true)
@@ -973,7 +838,7 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroupId);
contactGroup.getId());
will(returnValue(messageMetadata));
oneOf(clientHelper).getMessageAsList(txn, messageId);
will(returnValue(body));
@@ -990,6 +855,8 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
@Test
public void testGetLocalUpdateNoMailbox() throws Exception {
Transaction txn = new Transaction(null, false);
Contact contact = getContact();
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
BdfDictionary metaDictionary = BdfDictionary.of(
new BdfEntry(MSG_KEY_VERSION, 1),
new BdfEntry(MSG_KEY_LOCAL, true)
@@ -1007,7 +874,7 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroupId);
contactGroup.getId());
will(returnValue(messageMetadata));
oneOf(clientHelper).getMessageAsList(txn, messageId);
will(returnValue(body));
@@ -1042,24 +909,4 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
false);
}});
}
private void assertNoMailboxPropertiesSent(
MailboxUpdateSentToNewContactEvent e,
List<MailboxVersion> clientSupports) {
assertEquals(contact.getId(), e.getContactId());
MailboxUpdate u = e.getMailboxUpdate();
assertEquals(clientSupports, u.getClientSupports());
assertFalse(u.hasMailbox());
}
private void assertMailboxPropertiesSent(
MailboxUpdateSentToNewContactEvent e,
List<MailboxVersion> clientSupports) {
assertEquals(contact.getId(), e.getContactId());
MailboxUpdate u = e.getMailboxUpdate();
assertEquals(clientSupports, u.getClientSupports());
assertTrue(u.hasMailbox());
MailboxUpdateWithMailbox uMailbox = (MailboxUpdateWithMailbox) u;
assertEquals(updateProps, uMailbox.getMailboxProperties());
}
}

View File

@@ -1,16 +1,12 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.Cancellable;
import org.briarproject.bramble.api.connection.ConnectionRegistry;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.mailbox.MailboxFolderId;
import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent;
import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.OutgoingSessionRecord;
import org.briarproject.bramble.api.sync.event.MessageSharedEvent;
@@ -29,13 +25,10 @@ import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicReference;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.briarproject.bramble.api.mailbox.MailboxConstants.CLIENT_SUPPORTS;
import static org.briarproject.bramble.api.mailbox.MailboxConstants.MAX_LATENCY;
@@ -57,8 +50,6 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
private final TaskScheduler taskScheduler =
context.mock(TaskScheduler.class);
private final EventBus eventBus = context.mock(EventBus.class);
private final ConnectionRegistry connectionRegistry =
context.mock(ConnectionRegistry.class);
private final ConnectivityChecker connectivityChecker =
context.mock(ConnectivityChecker.class);
private final MailboxApiCaller mailboxApiCaller =
@@ -81,9 +72,6 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
private final MessageId ackedId = new MessageId(getRandomId());
private final MessageId sentId = new MessageId(getRandomId());
private final MessageId newMessageId = new MessageId(getRandomId());
private final GroupId groupId = new GroupId(getRandomId());
private final Map<ContactId, Boolean> groupVisibility =
singletonMap(contactId, true);
private File testDir, tempFile;
private MailboxUploadWorker worker;
@@ -93,9 +81,8 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
testDir = getTestDirectory();
tempFile = new File(testDir, "temp");
worker = new MailboxUploadWorker(ioExecutor, db, clock, taskScheduler,
eventBus, connectionRegistry, connectivityChecker,
mailboxApiCaller, mailboxApi, mailboxFileManager,
mailboxProperties, folderId, contactId);
eventBus, connectivityChecker, mailboxApiCaller, mailboxApi,
mailboxFileManager, mailboxProperties, folderId, contactId);
}
@After
@@ -106,11 +93,8 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
@Test
public void testChecksForDataWhenStartedAndRemovesObserverWhenDestroyed()
throws Exception {
// When the worker is started it should check the connection registry.
// We're not connected to the contact, so the worker should check for
// data to send
// When the worker is started it should check for data to send
expectRunTaskOnIoExecutor();
expectCheckConnectionRegistry(false);
expectCheckForDataToSendNoDataWaiting();
worker.start();
@@ -122,59 +106,15 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
worker.destroy();
}
@Test
public void testDoesNotCheckForDataWhenStartedIfConnectedToContact() {
// When the worker is started it should check the connection registry.
// We're connected to the contact, so the worker should not check for
// data to send
expectRunTaskOnIoExecutor();
expectCheckConnectionRegistry(true);
worker.start();
// When the worker is destroyed it should remove the connectivity
// observer and event listener
expectRemoveObserverAndListener();
worker.destroy();
}
@Test
public void testChecksForDataWhenContactDisconnects() throws Exception {
// When the worker is started it should check the connection registry.
// We're connected to the contact, so the worker should not check for
// data to send
expectRunTaskOnIoExecutor();
expectCheckConnectionRegistry(true);
worker.start();
// When the contact disconnects, the worker should start a task to
// check for data to send
expectRunTaskOnIoExecutor();
expectCheckConnectionRegistry(false);
expectCheckForDataToSendNoDataWaiting();
worker.eventOccurred(new ContactDisconnectedEvent(contactId));
// When the worker is destroyed it should remove the connectivity
// observer and event listener
expectRemoveObserverAndListener();
worker.destroy();
}
@Test
public void testChecksConnectivityWhenStartedIfDataIsReady()
throws Exception {
Transaction recordTxn = new Transaction(null, false);
// When the worker is started it should check the connection registry.
// We're not connected to the contact, so the worker should check for
// data to send. As there's data ready to send immediately, the worker
// should start a connectivity check
// When the worker is started it should check for data to send. As
// there's data ready to send immediately, the worker should start a
// connectivity check
expectRunTaskOnIoExecutor();
expectCheckConnectionRegistry(false);
expectCheckForDataToSendAndStartConnectivityCheck();
worker.start();
@@ -209,9 +149,7 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
worker.onConnectivityCheckSucceeded();
// When the upload task runs, it should upload the file, record
// the acked/sent messages in the DB, and check the connection
// registry. We're not connected to the contact, so the worker should
// check for more data to send
// the acked/sent messages in the DB, and check for more data to send
context.checking(new DbExpectations() {{
oneOf(mailboxApi).addFile(mailboxProperties, folderId, tempFile);
oneOf(db).transaction(with(false), withDbRunnable(recordTxn));
@@ -219,7 +157,6 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
oneOf(db).setMessagesSent(recordTxn, contactId,
singletonList(sentId), MAX_LATENCY);
}});
expectCheckConnectionRegistry(false);
expectCheckForDataToSendNoDataWaiting();
assertFalse(upload.get().callApi());
@@ -234,42 +171,12 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
assertFalse(tempFile.exists());
}
@Test
public void testDoesNotWriteFileIfContactConnectsDuringConnectivityCheck()
throws Exception {
// When the worker is started it should check the connection registry.
// We're not connected to the contact, so the worker should check for
// data to send. As there's data ready to send immediately, the worker
// should start a connectivity check
expectRunTaskOnIoExecutor();
expectCheckConnectionRegistry(false);
expectCheckForDataToSendAndStartConnectivityCheck();
worker.start();
// Before the connectivity check succeeds, we make a direct connection
// to the contact
worker.eventOccurred(new ContactConnectedEvent(contactId));
// When the connectivity check succeeds, the worker should not start
// writing and uploading a file
worker.onConnectivityCheckSucceeded();
// When the worker is destroyed it should remove the connectivity
// observer and event listener
expectRemoveObserverAndListener();
worker.destroy();
}
@Test
public void testCancelsApiCallWhenDestroyed() throws Exception {
// When the worker is started it should check the connection registry.
// We're not connected to the contact, so the worker should check for
// data to send. As there's data ready to send immediately, the worker
// should start a connectivity check
// When the worker is started it should check for data to send. As
// there's data ready to send immediately, the worker should start a
// connectivity check
expectRunTaskOnIoExecutor();
expectCheckConnectionRegistry(false);
expectCheckForDataToSendAndStartConnectivityCheck();
worker.start();
@@ -305,7 +212,9 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
// When the worker is destroyed it should remove the connectivity
// observer and event listener and cancel the upload task
expectCancelTask(apiCall);
context.checking(new Expectations() {{
oneOf(apiCall).cancel();
}});
expectRemoveObserverAndListener();
worker.destroy();
@@ -321,21 +230,16 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
@Test
public void testSchedulesWakeupWhenStartedIfDataIsNotReady()
throws Exception {
// When the worker is started it should check the connection registry.
// We're not connected to the contact, so the worker should check for
// data to send. As the data isn't ready to send immediately, the
// worker should schedule a wakeup
// When the worker is started it should check for data to send. As
// the data isn't ready to send immediately, the worker should
// schedule a wakeup
expectRunTaskOnIoExecutor();
AtomicReference<Runnable> wakeup = new AtomicReference<>();
expectCheckConnectionRegistry(false);
expectCheckForDataToSendAndScheduleWakeup(wakeup);
worker.start();
// When the wakeup task runs it should check the connection registry.
// We're not connected to the contact, so the worker should check for
// data to send
expectCheckConnectionRegistry(false);
// When the wakeup task runs it should check for data to send
expectCheckForDataToSendNoDataWaiting();
wakeup.get().run();
@@ -348,51 +252,21 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
}
@Test
public void testCancelsWakeupIfContactConnectsBeforeWakingUp()
throws Exception {
public void testCancelsWakeupIfDestroyedBeforeWakingUp() throws Exception {
// When the worker is started it should check for data to send. As
// the data isn't ready to send immediately, the worker should
// schedule a wakeup
expectRunTaskOnIoExecutor();
AtomicReference<Runnable> wakeup = new AtomicReference<>();
expectCheckConnectionRegistry(false);
expectCheckForDataToSendAndScheduleWakeup(wakeup);
worker.start();
// Before the wakeup task runs, we make a direct connection to the
// contact. The worker should cancel the wakeup task
expectCancelTask(wakeupTask);
worker.eventOccurred(new ContactConnectedEvent(contactId));
// If the wakeup task runs anyway (cancellation came too late), it
// should return without doing anything
wakeup.get().run();
// When the worker is destroyed it should remove the connectivity
// observer and event listener
expectRemoveObserverAndListener();
worker.destroy();
}
@Test
public void testCancelsWakeupIfDestroyedBeforeWakingUp() throws Exception {
// When the worker is started it should check the connection registry.
// We're not connected to the contact, so the worker should check for
// data to send. As the data isn't ready to send immediately, the
// worker should schedule a wakeup
expectRunTaskOnIoExecutor();
expectCheckConnectionRegistry(false);
AtomicReference<Runnable> wakeup = new AtomicReference<>();
expectCheckForDataToSendAndScheduleWakeup(wakeup);
worker.start();
// When the worker is destroyed it should cancel the wakeup and
// remove the connectivity observer and event listener
expectCancelTask(wakeupTask);
context.checking(new Expectations() {{
oneOf(wakeupTask).cancel();
}});
expectRemoveObserverAndListener();
worker.destroy();
@@ -405,12 +279,10 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
@Test
public void testCancelsWakeupIfEventIsReceivedBeforeWakingUp()
throws Exception {
// When the worker is started it should check the connection registry.
// We're not connected to the contact, so the worker should check for
// data to send. As the data isn't ready to send immediately, the
// worker should schedule a wakeup
// When the worker is started it should check for data to send. As
// the data isn't ready to send immediately, the worker should
// schedule a wakeup
expectRunTaskOnIoExecutor();
expectCheckConnectionRegistry(false);
AtomicReference<Runnable> wakeup = new AtomicReference<>();
expectCheckForDataToSendAndScheduleWakeup(wakeup);
@@ -421,10 +293,11 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
// wakeup task and schedule a check for new data after a short delay
AtomicReference<Runnable> check = new AtomicReference<>();
expectScheduleCheck(check, CHECK_DELAY_MS);
expectCancelTask(wakeupTask);
context.checking(new Expectations() {{
oneOf(wakeupTask).cancel();
}});
worker.eventOccurred(new MessageSharedEvent(newMessageId, groupId,
groupVisibility));
worker.eventOccurred(new MessageSharedEvent(newMessageId));
// If the wakeup task runs anyway (cancellation came too late), it
// should return early when it finds the state has changed
@@ -433,13 +306,9 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
// Before the check task runs, the worker receives another event that
// indicates new data may be available. The event should be ignored,
// as a check for new data has already been scheduled
worker.eventOccurred(new MessageSharedEvent(newMessageId, groupId,
groupVisibility));
worker.eventOccurred(new MessageSharedEvent(newMessageId));
// When the check task runs, it should check the connection registry.
// We're not connected to the contact, so the worker should check for
// new data
expectCheckConnectionRegistry(false);
// When the check task runs, it should check for new data
expectCheckForDataToSendNoDataWaiting();
check.get().run();
@@ -453,11 +322,8 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
@Test
public void testCancelsCheckWhenDestroyed() throws Exception {
// When the worker is started it should check the connection registry.
// We're not connected to the contact, so the worker should check for
// data to send
// When the worker is started it should check for data to send
expectRunTaskOnIoExecutor();
expectCheckConnectionRegistry(false);
expectCheckForDataToSendNoDataWaiting();
worker.start();
@@ -468,12 +334,13 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
AtomicReference<Runnable> check = new AtomicReference<>();
expectScheduleCheck(check, CHECK_DELAY_MS);
worker.eventOccurred(new MessageSharedEvent(newMessageId, groupId,
groupVisibility));
worker.eventOccurred(new MessageSharedEvent(newMessageId));
// When the worker is destroyed it should cancel the check and
// remove the connectivity observer and event listener
expectCancelTask(checkTask);
context.checking(new Expectations() {{
oneOf(checkTask).cancel();
}});
expectRemoveObserverAndListener();
worker.destroy();
@@ -483,100 +350,13 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
check.get().run();
}
@Test
public void testCancelsCheckIfContactConnects() throws Exception {
// When the worker is started it should check the connection registry.
// We're not connected to the contact, so the worker should check for
// data to send
expectRunTaskOnIoExecutor();
expectCheckConnectionRegistry(false);
expectCheckForDataToSendNoDataWaiting();
worker.start();
// The worker receives an event that indicates new data may be
// available. The worker should schedule a check for new data after
// a short delay
AtomicReference<Runnable> check = new AtomicReference<>();
expectScheduleCheck(check, CHECK_DELAY_MS);
worker.eventOccurred(new MessageSharedEvent(newMessageId, groupId,
groupVisibility));
// Before the check task runs, we make a direct connection to the
// contact. The worker should cancel the check
expectCancelTask(checkTask);
worker.eventOccurred(new ContactConnectedEvent(contactId));
// If the check runs anyway (cancellation came too late), it should
// return early when it finds the state has changed
check.get().run();
// When the worker is destroyed it should remove the connectivity
// observer and event listener
expectRemoveObserverAndListener();
worker.destroy();
}
@Test
public void testDoesNotScheduleCheckIfGroupIsVisible() throws Exception {
// When the worker is started it should check the connection registry.
// We're not connected to the contact, so the worker should check for
// data to send
expectRunTaskOnIoExecutor();
expectCheckConnectionRegistry(false);
expectCheckForDataToSendNoDataWaiting();
worker.start();
// The worker receives an event that indicates new data may be
// available. The group is visible to the contact but not shared, so
// the worker should not schedule a check for new data
worker.eventOccurred(new MessageSharedEvent(newMessageId, groupId,
singletonMap(contactId, false)));
// When the worker is destroyed it should remove the connectivity
// observer and event listener
expectRemoveObserverAndListener();
worker.destroy();
}
@Test
public void testDoesNotScheduleCheckIfGroupIsInvisible() throws Exception {
// When the worker is started it should check the connection registry.
// We're not connected to the contact, so the worker should check for
// data to send
expectRunTaskOnIoExecutor();
expectCheckConnectionRegistry(false);
expectCheckForDataToSendNoDataWaiting();
worker.start();
// The worker receives an event that indicates new data may be
// available. The group is not visible to the contact, so the worker
// should not schedule a check for new data
worker.eventOccurred(new MessageSharedEvent(newMessageId, groupId,
emptyMap()));
// When the worker is destroyed it should remove the connectivity
// observer and event listener
expectRemoveObserverAndListener();
worker.destroy();
}
@Test
public void testRetriesAfterDelayIfExceptionOccursWhileWritingFile()
throws Exception {
// When the worker is started it should check the connection registry.
// We're not connected to the contact, so the worker should check for
// data to send. As there's data ready to send immediately, the worker
// should start a connectivity check
// When the worker is started it should check for data to send. As
// there's data ready to send immediately, the worker should start a
// connectivity check
expectRunTaskOnIoExecutor();
expectCheckConnectionRegistry(false);
expectCheckForDataToSendAndStartConnectivityCheck();
worker.start();
@@ -595,10 +375,7 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
worker.onConnectivityCheckSucceeded();
// When the check task runs it should check the connection registry.
// We're not connected to the contact, so the worker should check for
// new data
expectCheckConnectionRegistry(false);
// When the check task runs it should check for new data
expectCheckForDataToSendNoDataWaiting();
check.get().run();
@@ -610,13 +387,6 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
worker.destroy();
}
private void expectCheckConnectionRegistry(boolean connected) {
context.checking(new Expectations() {{
oneOf(connectionRegistry).isConnected(contactId);
will(returnValue(connected));
}});
}
private void expectRunTaskOnIoExecutor() {
context.checking(new Expectations() {{
oneOf(ioExecutor).execute(with(any(Runnable.class)));
@@ -686,12 +456,6 @@ public class MailboxUploadWorkerTest extends BrambleMockTestCase {
}});
}
private void expectCancelTask(Cancellable task) {
context.checking(new Expectations() {{
oneOf(task).cancel();
}});
}
private void expectRemoveObserverAndListener() {
context.checking(new Expectations() {{
oneOf(connectivityChecker).removeObserver(worker);

View File

@@ -1,22 +1,13 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.Cancellable;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.mailbox.MailboxFolderId;
import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.system.TaskScheduler;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.CaptureArgumentAction;
import org.jmock.Expectations;
import org.jmock.lib.action.DoAllAction;
import org.junit.Test;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import static org.briarproject.bramble.api.mailbox.MailboxConstants.CLIENT_SUPPORTS;
import static org.briarproject.bramble.mailbox.OwnMailboxClient.CONNECTIVITY_CHECK_INTERVAL_MS;
import static org.briarproject.bramble.test.TestUtils.getContactId;
import static org.briarproject.bramble.test.TestUtils.getMailboxProperties;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
@@ -29,9 +20,6 @@ public class OwnMailboxClientTest extends BrambleMockTestCase {
context.mock(ConnectivityChecker.class);
private final TorReachabilityMonitor reachabilityMonitor =
context.mock(TorReachabilityMonitor.class);
private final TaskScheduler taskScheduler =
context.mock(TaskScheduler.class);
private final Executor ioExecutor = context.mock(Executor.class);
private final MailboxWorker contactListWorker =
context.mock(MailboxWorker.class, "contactListWorker");
private final MailboxWorker uploadWorker1 =
@@ -40,8 +28,6 @@ public class OwnMailboxClientTest extends BrambleMockTestCase {
context.mock(MailboxWorker.class, "uploadWorker2");
private final MailboxWorker downloadWorker =
context.mock(MailboxWorker.class, "downloadWorker");
private final Cancellable connectivityCheck =
context.mock(Cancellable.class);
private final MailboxProperties properties =
getMailboxProperties(true, CLIENT_SUPPORTS);
@@ -54,24 +40,21 @@ public class OwnMailboxClientTest extends BrambleMockTestCase {
public OwnMailboxClientTest() {
expectCreateContactListWorker();
client = new OwnMailboxClient(workerFactory, connectivityChecker,
reachabilityMonitor, taskScheduler, ioExecutor, properties);
reachabilityMonitor, properties);
context.assertIsSatisfied();
}
@Test
public void testStartAndDestroyWithNoContactsAssigned() {
expectStartConnectivityCheck();
expectStartWorker(contactListWorker);
client.start();
expectDestroyWorker(contactListWorker);
expectDestroyConnectivityChecker();
client.destroy();
}
@Test
public void testAssignContactForUploadAndDestroyClient() {
expectStartConnectivityCheck();
expectStartWorker(contactListWorker);
client.start();
@@ -84,13 +67,11 @@ public class OwnMailboxClientTest extends BrambleMockTestCase {
// When the client is destroyed, the worker should be destroyed
expectDestroyWorker(uploadWorker1);
expectDestroyWorker(contactListWorker);
expectDestroyConnectivityChecker();
client.destroy();
}
@Test
public void testAssignAndDeassignContactForUpload() {
expectStartConnectivityCheck();
expectStartWorker(contactListWorker);
client.start();
@@ -106,13 +87,11 @@ public class OwnMailboxClientTest extends BrambleMockTestCase {
context.assertIsSatisfied();
expectDestroyWorker(contactListWorker);
expectDestroyConnectivityChecker();
client.destroy();
}
@Test
public void testAssignAndDeassignTwoContactsForUpload() {
expectStartConnectivityCheck();
expectStartWorker(contactListWorker);
client.start();
@@ -141,13 +120,11 @@ public class OwnMailboxClientTest extends BrambleMockTestCase {
context.assertIsSatisfied();
expectDestroyWorker(contactListWorker);
expectDestroyConnectivityChecker();
client.destroy();
}
@Test
public void testAssignContactForDownloadAndDestroyClient() {
expectStartConnectivityCheck();
expectStartWorker(contactListWorker);
client.start();
@@ -160,13 +137,11 @@ public class OwnMailboxClientTest extends BrambleMockTestCase {
// When the client is destroyed, the worker should be destroyed
expectDestroyWorker(downloadWorker);
expectDestroyWorker(contactListWorker);
expectDestroyConnectivityChecker();
client.destroy();
}
@Test
public void testAssignAndDeassignTwoContactsForDownload() {
expectStartConnectivityCheck();
expectStartWorker(contactListWorker);
client.start();
@@ -191,72 +166,9 @@ public class OwnMailboxClientTest extends BrambleMockTestCase {
context.assertIsSatisfied();
expectDestroyWorker(contactListWorker);
expectDestroyConnectivityChecker();
client.destroy();
}
@Test
public void testCancelsConnectivityCheckWhenClientIsDestroyed() {
expectStartConnectivityCheck();
expectStartWorker(contactListWorker);
client.start();
// When the first connectivity check succeeds, the worker should
// schedule a second check
AtomicReference<Runnable> task = new AtomicReference<>();
expectScheduleConnectivityCheck(task);
client.onConnectivityCheckSucceeded();
// When the task runs, the worker should check the mailbox's
// connectivity
expectStartConnectivityCheck();
task.get().run();
// When the second connectivity check succeeds, the worker should
// schedule a third check
expectScheduleConnectivityCheck(task);
client.onConnectivityCheckSucceeded();
// When the client is destroyed, the scheduled check should be cancelled
expectDestroyWorker(contactListWorker);
expectDestroyConnectivityChecker();
context.checking(new Expectations() {{
oneOf(connectivityCheck).cancel();
}});
client.destroy();
// If the task runs anyway (cancellation came too late), it should
// return when it finds that the client has been destroyed
task.get().run();
}
@Test
public void testIgnoresConnectivityResultWhenClientIsDestroyed() {
expectStartConnectivityCheck();
expectStartWorker(contactListWorker);
client.start();
// When the first connectivity check succeeds, the worker should
// schedule a second check
AtomicReference<Runnable> task = new AtomicReference<>();
expectScheduleConnectivityCheck(task);
client.onConnectivityCheckSucceeded();
// When the task runs, the worker should check the mailbox's
// connectivity
expectStartConnectivityCheck();
task.get().run();
// Before the connectivity check succeeds, the client is destroyed
expectDestroyWorker(contactListWorker);
expectDestroyConnectivityChecker();
client.destroy();
// If the connectivity check succeeds despite the connectivity checker
// having been destroyed, the client should not schedule another check
client.onConnectivityCheckSucceeded();
}
private void expectCreateContactListWorker() {
context.checking(new Expectations() {{
oneOf(workerFactory).createContactListWorkerForOwnMailbox(
@@ -288,34 +200,9 @@ public class OwnMailboxClientTest extends BrambleMockTestCase {
}});
}
private void expectStartConnectivityCheck() {
context.checking(new Expectations() {{
oneOf(connectivityChecker).checkConnectivity(properties, client);
}});
}
private void expectScheduleConnectivityCheck(
AtomicReference<Runnable> task) {
context.checking(new Expectations() {{
oneOf(taskScheduler).schedule(with(any(Runnable.class)),
with(ioExecutor), with(CONNECTIVITY_CHECK_INTERVAL_MS),
with(TimeUnit.MILLISECONDS));
will(new DoAllAction(
new CaptureArgumentAction<>(task, Runnable.class, 0),
returnValue(connectivityCheck)
));
}});
}
private void expectDestroyWorker(MailboxWorker worker) {
context.checking(new Expectations() {{
oneOf(worker).destroy();
}});
}
private void expectDestroyConnectivityChecker() {
context.checking(new Expectations() {{
oneOf(connectivityChecker).destroy();
}});
}
}

View File

@@ -0,0 +1,25 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Before;
import org.junit.Test;
import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.createTestComponent;
import static org.junit.Assert.assertTrue;
public class OwnMailboxContactListWorkerIntegrationTest
extends BrambleTestCase {
private MailboxIntegrationTestComponent component;
@Before
public void setUp() {
component = createTestComponent();
}
// Just test that we can build the component. TODO: Write actual tests
@Test
public void testBuild() {
assertTrue(true);
}
}

View File

@@ -12,11 +12,9 @@ import org.briarproject.bramble.event.DefaultEventExecutorModule;
import org.briarproject.bramble.system.DefaultWakefulIoExecutorModule;
import org.briarproject.bramble.system.TimeTravelModule;
import org.briarproject.bramble.test.TestDatabaseConfigModule;
import org.briarproject.bramble.test.TestDnsModule;
import org.briarproject.bramble.test.TestFeatureFlagModule;
import org.briarproject.bramble.test.TestMailboxDirectoryModule;
import org.briarproject.bramble.test.TestSecureRandomModule;
import org.briarproject.bramble.test.TestSocksModule;
import javax.inject.Singleton;
@@ -29,14 +27,12 @@ import dagger.Component;
DefaultEventExecutorModule.class,
DefaultWakefulIoExecutorModule.class,
TestDatabaseConfigModule.class,
TestDnsModule.class,
TestFeatureFlagModule.class,
TestMailboxDirectoryModule.class,
RemovableDriveIntegrationTestModule.class,
RemovableDriveModule.class,
TestSecureRandomModule.class,
TimeTravelModule.class,
TestSocksModule.class
TimeTravelModule.class
})
interface RemovableDriveIntegrationTestComponent
extends BrambleCoreEagerSingletons {

View File

@@ -14,13 +14,11 @@ import org.briarproject.bramble.api.sync.SyncRecordWriter;
import org.briarproject.bramble.api.sync.Versions;
import org.briarproject.bramble.api.transport.StreamWriter;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.CaptureArgumentAction;
import org.briarproject.bramble.test.DbExpectations;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
@@ -70,10 +68,13 @@ public class MailboxOutgoingSessionTest extends BrambleMockTestCase {
oneOf(eventBus).addListener(session);
// Send the protocol versions
oneOf(recordWriter).writeVersions(with(any(Versions.class)));
// Calculate capacity for acks
oneOf(recordWriter).getBytesWritten();
will(returnValue((long) versionRecordBytes));
// No messages to ack
oneOf(db).transactionWithResult(with(true),
withDbCallable(noAckIdTxn));
oneOf(db).getMessagesToAck(noAckIdTxn, contactId);
oneOf(db).getMessagesToAck(noAckIdTxn, contactId, MAX_MESSAGE_IDS);
will(returnValue(emptyList()));
// Calculate capacity for messages
oneOf(recordWriter).getBytesWritten();
@@ -105,6 +106,7 @@ public class MailboxOutgoingSessionTest extends BrambleMockTestCase {
MAX_FILE_PAYLOAD_BYTES);
Transaction ackIdTxn = new Transaction(null, true);
Transaction noAckIdTxn = new Transaction(null, true);
Transaction msgIdTxn = new Transaction(null, true);
Transaction msgTxn = new Transaction(null, true);
@@ -112,24 +114,28 @@ public class MailboxOutgoingSessionTest extends BrambleMockTestCase {
long capacityForMessages =
MAX_FILE_PAYLOAD_BYTES - versionRecordBytes - ackRecordBytes;
AtomicReference<Ack> ack = new AtomicReference<>();
context.checking(new DbExpectations() {{
// Add listener
oneOf(eventBus).addListener(session);
// Send the protocol versions
oneOf(recordWriter).writeVersions(with(any(Versions.class)));
// Load the IDs to ack
oneOf(db).transactionWithResult(with(true),
withDbCallable(ackIdTxn));
oneOf(db).getMessagesToAck(ackIdTxn, contactId);
will(returnValue(singletonList(message.getId())));
// Calculate capacity for acks
oneOf(recordWriter).getBytesWritten();
will(returnValue((long) versionRecordBytes));
// One message to ack
oneOf(db).transactionWithResult(with(true),
withDbCallable(ackIdTxn));
oneOf(db).getMessagesToAck(ackIdTxn, contactId, MAX_MESSAGE_IDS);
will(returnValue(singletonList(message.getId())));
// Send the ack
oneOf(recordWriter).getBytesWritten();
will(returnValue((long) versionRecordBytes));
oneOf(recordWriter).writeAck(with(any(Ack.class)));
will(new CaptureArgumentAction<>(ack, Ack.class, 0));
// No more messages to ack
oneOf(db).transactionWithResult(with(true),
withDbCallable(noAckIdTxn));
oneOf(db).getMessagesToAck(noAckIdTxn, contactId, MAX_MESSAGE_IDS);
will(returnValue(emptyList()));
// Calculate capacity for messages
oneOf(recordWriter).getBytesWritten();
will(returnValue((long) versionRecordBytes + ackRecordBytes));
@@ -156,7 +162,6 @@ public class MailboxOutgoingSessionTest extends BrambleMockTestCase {
assertEquals(singletonList(message.getId()),
sessionRecord.getAckedIds());
assertEquals(singletonList(message.getId()), ack.get().getMessageIds());
assertEquals(singletonList(message1.getId()),
sessionRecord.getSentIds());
}
@@ -173,50 +178,48 @@ public class MailboxOutgoingSessionTest extends BrambleMockTestCase {
eventBus, contactId, transportId, MAX_LATENCY,
streamWriter, recordWriter, sessionRecord, capacity);
Transaction ackIdTxn = new Transaction(null, true);
Transaction ackIdTxn1 = new Transaction(null, true);
Transaction ackIdTxn2 = new Transaction(null, true);
int firstAckRecordBytes =
RECORD_HEADER_BYTES + MessageId.LENGTH * MAX_MESSAGE_IDS;
int secondAckRecordBytes = RECORD_HEADER_BYTES + MessageId.LENGTH;
// There are MAX_MESSAGE_IDS + 2 messages that need to be acked, but
// only enough capacity to ack MAX_MESSAGE_IDS + 1 messages
List<MessageId> idsToAck = new ArrayList<>(MAX_MESSAGE_IDS + 2);
for (int i = 0; i < MAX_MESSAGE_IDS + 2; i++) {
idsToAck.add(new MessageId(getRandomId()));
List<MessageId> idsInFirstAck = new ArrayList<>(MAX_MESSAGE_IDS);
for (int i = 0; i < MAX_MESSAGE_IDS; i++) {
idsInFirstAck.add(new MessageId(getRandomId()));
}
// The first ack contains MAX_MESSAGE_IDS IDs
List<MessageId> idsInFirstAck = idsToAck.subList(0, MAX_MESSAGE_IDS);
// The second ack contains one ID
List<MessageId> idsInSecondAck =
idsToAck.subList(MAX_MESSAGE_IDS, MAX_MESSAGE_IDS + 1);
List<MessageId> idsAcked = idsToAck.subList(0, MAX_MESSAGE_IDS + 1);
AtomicReference<Ack> firstAck = new AtomicReference<>();
AtomicReference<Ack> secondAck = new AtomicReference<>();
singletonList(new MessageId(getRandomId()));
List<MessageId> allIds = new ArrayList<>(MAX_MESSAGE_IDS + 1);
allIds.addAll(idsInFirstAck);
allIds.addAll(idsInSecondAck);
context.checking(new DbExpectations() {{
// Add listener
oneOf(eventBus).addListener(session);
// Send the protocol versions
oneOf(recordWriter).writeVersions(with(any(Versions.class)));
// Load the IDs to ack
oneOf(db).transactionWithResult(with(true),
withDbCallable(ackIdTxn));
oneOf(db).getMessagesToAck(ackIdTxn, contactId);
will(returnValue(idsToAck));
// Calculate capacity for acks
oneOf(recordWriter).getBytesWritten();
will(returnValue((long) versionRecordBytes));
// Load the IDs for the first ack record
oneOf(db).transactionWithResult(with(true),
withDbCallable(ackIdTxn1));
oneOf(db).getMessagesToAck(ackIdTxn1, contactId, MAX_MESSAGE_IDS);
will(returnValue(idsInFirstAck));
// Send the first ack record
oneOf(recordWriter).writeAck(with(any(Ack.class)));
will(new CaptureArgumentAction<>(firstAck, Ack.class, 0));
// Calculate remaining capacity for acks
oneOf(recordWriter).getBytesWritten();
will(returnValue((long) versionRecordBytes + firstAckRecordBytes));
// Load the IDs for the second ack record
oneOf(db).transactionWithResult(with(true),
withDbCallable(ackIdTxn2));
oneOf(db).getMessagesToAck(ackIdTxn2, contactId, 1);
will(returnValue(idsInSecondAck));
// Send the second ack record
oneOf(recordWriter).writeAck(with(any(Ack.class)));
will(new CaptureArgumentAction<>(secondAck, Ack.class, 0));
// Not enough capacity left for another ack
oneOf(recordWriter).getBytesWritten();
will(returnValue((long) versionRecordBytes + firstAckRecordBytes
@@ -233,9 +236,7 @@ public class MailboxOutgoingSessionTest extends BrambleMockTestCase {
session.run();
assertEquals(idsAcked, sessionRecord.getAckedIds());
assertEquals(idsInFirstAck, firstAck.get().getMessageIds());
assertEquals(idsInSecondAck, secondAck.get().getMessageIds());
assertEquals(allIds, sessionRecord.getAckedIds());
assertEquals(emptyList(), sessionRecord.getSentIds());
}
}

View File

@@ -3,8 +3,6 @@ package org.briarproject.bramble.sync;
import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons;
import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.bramble.test.TestDnsModule;
import org.briarproject.bramble.test.TestSocksModule;
import javax.inject.Singleton;
@@ -13,9 +11,7 @@ import dagger.Component;
@Singleton
@Component(modules = {
BrambleCoreIntegrationTestModule.class,
BrambleCoreModule.class,
TestDnsModule.class,
TestSocksModule.class
BrambleCoreModule.class
})
interface SyncIntegrationTestComponent extends
BrambleCoreIntegrationTestEagerSingletons {

View File

@@ -14,9 +14,7 @@ import dagger.Component;
@Singleton
@Component(modules = {
BrambleCoreIntegrationTestModule.class,
BrambleCoreModule.class,
TestDnsModule.class,
TestSocksModule.class
BrambleCoreModule.class
})
public interface BrambleIntegrationTestComponent
extends BrambleCoreIntegrationTestEagerSingletons {

View File

@@ -9,8 +9,6 @@ import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.transport.KeyManager;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.bramble.test.BrambleIntegrationTestComponent;
import org.briarproject.bramble.test.TestDnsModule;
import org.briarproject.bramble.test.TestSocksModule;
import javax.inject.Singleton;
@@ -19,9 +17,7 @@ import dagger.Component;
@Singleton
@Component(modules = {
BrambleCoreIntegrationTestModule.class,
BrambleCoreModule.class,
TestDnsModule.class,
TestSocksModule.class
BrambleCoreModule.class
})
interface TransportKeyAgreementTestComponent
extends BrambleIntegrationTestComponent {

View File

@@ -1,15 +1,23 @@
dependencyVerification {
verify = [
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'ch.qos.logback:logback-classic:1.2.10:logback-classic-1.2.10.jar:3160ae988af82c8bf3024ddbe034a82da98bb186fd09e76c50543c5b9da5cc5e',
'ch.qos.logback:logback-core:1.2.10:logback-core-1.2.10.jar:ba51a3fe56691f9dd7fe742e4a73c3ab4aaaa32202c73409ba56f18687399a08',
'com.fasterxml.jackson.core:jackson-annotations:2.13.0:jackson-annotations-2.13.0.jar:81f9724d8843e8b08f8f6c0609e7a2b030d00c34861c4ac7e2099a7235047d6f',
'com.fasterxml.jackson.core:jackson-annotations:2.13.3:jackson-annotations-2.13.3.jar:5326a6fbcde7cf8817f36c254101cd45f6acea4258518cd3c80ee5b89f4e4b9b',
'com.fasterxml.jackson.core:jackson-core:2.13.0:jackson-core-2.13.0.jar:348bc59b348df2e807b356f1d62d2afb41a974073328abc773eb0932b855d2c8',
'com.fasterxml.jackson.core:jackson-core:2.13.3:jackson-core-2.13.3.jar:ab119a8ea3cc69472ebc0e870b849bfbbe536ad57d613dc38453ccd592ca6a3d',
'com.fasterxml.jackson.core:jackson-databind:2.13.0:jackson-databind-2.13.0.jar:9c826d27176268777adcf97e1c6e2051c7e33a7aaa2c370c2e8c6077fd9da3f4',
'com.fasterxml.jackson.core:jackson-databind:2.13.3:jackson-databind-2.13.3.jar:6444bf08d8cd4629740afc3db1276938f494728deb663ce585c4e91f6b45eb84',
'com.fasterxml.jackson.module:jackson-module-kotlin:2.13.3:jackson-module-kotlin-2.13.3.jar:173b35e183756036457bb2e8d4ce26966fbf04da706a30b68ada69f4a2a14853',
'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger-compiler:2.33:dagger-compiler-2.33.jar:aa8a0d8370c578fd6999802d0d90b9829377a46d2c1141e11b8f737970e7155e',
'com.google.dagger:dagger-producers:2.33:dagger-producers-2.33.jar:5897f0b6eef799c2adfe3ccacc58c0fb374d58acb063c3ebe5366c38a8bce5c8',
'com.google.dagger:dagger-spi:2.33:dagger-spi-2.33.jar:e2dcab2221b8afb9556ef0a1c83b0bd5f42552e254322a257330f754cdbbb9d4',
'com.google.dagger:dagger:2.33:dagger-2.33.jar:d8798c5b8cf6b125234e33af5c6293bb9f2208ce29b57924c35b8c0be7b6bdcb',
'com.google.dagger:dagger:2.40:dagger-2.40.jar:b8cf6fd029e18c9bd3aab1e28127a4b2f696c02bc3d197f8aa08fbb92af2a22b',
'com.google.dagger:hilt-core:2.40:hilt-core-2.40.jar:92c4fea3770266036153259103c304436a4fdadaf861b6e20984029470d41382',
'com.google.errorprone:error_prone_annotations:2.2.0:error_prone_annotations-2.2.0.jar:6ebd22ca1b9d8ec06d41de8d64e0596981d9607b42035f9ed374f9de271a481a',
'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30',
'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e',
@@ -17,6 +25,8 @@ dependencyVerification {
'com.google.guava:guava:27.1-jre:guava-27.1-jre.jar:4a5aa70cc968a4d137e599ad37553e5cfeed2265e8c193476d7119036c536fe7',
'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6',
'com.google.zxing:core:3.4.1:core-3.4.1.jar:acfa30338c26267b6cab665509c2251bb96e8350bfcad89d59b949ba77011f8d',
'com.googlecode.json-simple:json-simple:1.1.1:json-simple-1.1.1.jar:4e69696892b88b41c55d49ab2fdcc21eead92bf54acc588c0050596c3b75199c',
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
'com.squareup.okhttp3:mockwebserver:4.9.3:mockwebserver-4.9.3.jar:9c8c581c29f22f877a35d11380462f75bb24bf1886204fe835ee695594a2784e',
'com.squareup.okhttp3:okhttp:3.12.13:okhttp-3.12.13.jar:508234e024ef7e270ab1a6d5b356f5b98e786511239ca986d684fd1e2cf7bc82',
@@ -24,11 +34,45 @@ dependencyVerification {
'com.squareup.okio:okio:1.15.0:okio-1.15.0.jar:693fa319a7e8843300602b204023b7674f106ebcb577f2dd5807212b66118bd2',
'com.squareup.okio:okio:2.8.0:okio-jvm-2.8.0.jar:4496b06e73982fcdd8a5393f46e5df2ce2fa4465df5895454cac68a32f09bbc8',
'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
'com.typesafe:config:1.4.1:config-1.4.1.jar:4c0aa7e223c75c8840c41fc183d4cd3118140a1ee503e3e08ce66ed2794c948f',
'io.ktor:ktor-client-core-jvm:2.0.3:ktor-client-core-jvm-2.0.3.jar:15828e1de6404ba95db6401b1180fc85bd7d7557e6f3351f555afe8f5e6f4b88',
'io.ktor:ktor-events-jvm:2.0.3:ktor-events-jvm-2.0.3.jar:5b0242430a39399bc9ecaf6879ffa94bf724005583eb71aa44fdf0ea14aadb23',
'io.ktor:ktor-http-cio-jvm:2.0.3:ktor-http-cio-jvm-2.0.3.jar:ee1f702dbf354627a46f87e6a5175cd6f6250171b4d918afcf1b0cbedccb82c4',
'io.ktor:ktor-http-jvm:2.0.3:ktor-http-jvm-2.0.3.jar:ef212ac976b9940bda91448533fc6c5723ffab36ba5134422cc5f04e41d018fb',
'io.ktor:ktor-io-jvm:2.0.3:ktor-io-jvm-2.0.3.jar:5c238469731a4ed300cef51062ce2ffcb672c9ecdee69a21b473173b712a77ce',
'io.ktor:ktor-network-jvm:2.0.3:ktor-network-jvm-2.0.3.jar:4b041d9fcfe4f0ac2dd85347da725a09e6e74ad9a131e58112240679952677df',
'io.ktor:ktor-serialization-jackson-jvm:2.0.3:ktor-serialization-jackson-jvm-2.0.3.jar:3468585257d9b4841a2a61a3c6c464427d6f42bc332dfb4c44de23b56efe6923',
'io.ktor:ktor-serialization-jvm:2.0.3:ktor-serialization-jvm-2.0.3.jar:af862165d247c91cc79f42b7daad4b705f1b96f33c4cef6a26b3b1690ccaae81',
'io.ktor:ktor-server-auth-jvm:2.0.3:ktor-server-auth-jvm-2.0.3.jar:41429c354a7455f41fae44186765df00bab7957f20d765eb9b4e160e770884a3',
'io.ktor:ktor-server-call-logging-jvm:2.0.3:ktor-server-call-logging-jvm-2.0.3.jar:e13023f0e434ba0dabd16212ded6ffab0d455933dde28e1189f787726f23ca5a',
'io.ktor:ktor-server-content-negotiation-jvm:2.0.3:ktor-server-content-negotiation-jvm-2.0.3.jar:6185baac8c2bf2fc7ffb66169b9cf02859d9eee405073df8921dd9b43bd45276',
'io.ktor:ktor-server-core-jvm:2.0.3:ktor-server-core-jvm-2.0.3.jar:70a58fc6cbf6cdef1bb49df3fc67bd6341b9c153683328d07cef901888b57a49',
'io.ktor:ktor-server-host-common-jvm:2.0.3:ktor-server-host-common-jvm-2.0.3.jar:86527c7d164384ef47551698018102bd5f730a4c382ff2e6281826546444ce80',
'io.ktor:ktor-server-netty-jvm:2.0.3:ktor-server-netty-jvm-2.0.3.jar:6e7f9665258c2ecf6ee1cf24501560db823385cec00bec9d96949f925f95d1f8',
'io.ktor:ktor-server-sessions-jvm:2.0.3:ktor-server-sessions-jvm-2.0.3.jar:d3517b86d97e49ff704eace7189cf52b15fb37c3dd79a4f24df930ba8c72405e',
'io.ktor:ktor-utils-jvm:2.0.3:ktor-utils-jvm-2.0.3.jar:2dadae1501fdcb2377065a6e333470f2f7876810e6dc394e6c075730e7df515b',
'io.ktor:ktor-websocket-serialization-jvm:2.0.3:ktor-websocket-serialization-jvm-2.0.3.jar:d5d773c4fbefec72b016155989332d87310374dc1fd1fd2ecc4072936dcf0e4e',
'io.ktor:ktor-websockets-jvm:2.0.3:ktor-websockets-jvm-2.0.3.jar:ce01043dcf7baa032d7fda7be08a861ec9b90cbac92b6489df69cc0c9c752544',
'io.netty:netty-buffer:4.1.77.Final:netty-buffer-4.1.77.Final.jar:41b7ddc4dd124c7e75af33a13a426fda4e1ec87c387cd234971e7df4c0b51c26',
'io.netty:netty-codec-http2:4.1.77.Final:netty-codec-http2-4.1.77.Final.jar:f2c3c1dc919fd694d1c4015143316811ed3c70edc6b0586851190305c2723296',
'io.netty:netty-codec-http:4.1.77.Final:netty-codec-http-4.1.77.Final.jar:96f6726f1f47273415665e8bf18f3b4ae28572fcb8845a7fe6e6d7ffdb8c48d2',
'io.netty:netty-codec:4.1.77.Final:netty-codec-4.1.77.Final.jar:84e4e01dd5b345311e971289b5bc08c0dfd6054a28d16853f0416943c9a3e458',
'io.netty:netty-common:4.1.77.Final:netty-common-4.1.77.Final.jar:40dd9b5ef14878f050a1f7f4d5647d53473f134e349665b47243bde56de7a51f',
'io.netty:netty-handler:4.1.77.Final:netty-handler-4.1.77.Final.jar:7911becd4850ff3fc3d93b4be7c468a2f6444fb48c17eec03c807856faf11e0a',
'io.netty:netty-resolver:4.1.77.Final:netty-resolver-4.1.77.Final.jar:0161cfe9544b3656ed0de67d8937828101859e94bcd0caaf58d21ac7011eabd4',
'io.netty:netty-transport-classes-epoll:4.1.77.Final:netty-transport-classes-epoll-4.1.77.Final.jar:0593fb942d7d57aadcc22360a238dcfac9f29013a20201ef49cc392b0dd2aaf9',
'io.netty:netty-transport-classes-kqueue:4.1.77.Final:netty-transport-classes-kqueue-4.1.77.Final.jar:4f27439bd83ae147b327dc0fdb9ff7315e93927b4054afe6ce8e64b0d78c85f5',
'io.netty:netty-transport-native-epoll:4.1.77.Final:netty-transport-native-epoll-4.1.77.Final.jar:ce87b3400ce5a869494007b67c1f2a4af4fe90c48e6ce7dd441cff01f5fa4015',
'io.netty:netty-transport-native-kqueue:4.1.77.Final:netty-transport-native-kqueue-4.1.77.Final.jar:e8a200301c087dd9278fb598d19e27d549d652cf9a38f8ad6a8167a35a51bdd6',
'io.netty:netty-transport-native-unix-common:4.1.77.Final:netty-transport-native-unix-common-4.1.77.Final.jar:108d27f325fa9ce9a914fa53638fbeeb1a384148fb3a13389bd09a5e38e4ac1e',
'io.netty:netty-transport:4.1.77.Final:netty-transport-4.1.77.Final.jar:034cdf7d81feaad9977c3d8b4fc05611952bc9861dfb9085b8962e2c1de582aa',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3',
'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11',
'net.i2p.crypto:eddsa:0.2.0:eddsa-0.2.0.jar:a7cb1b85c16e2f0730b9204106929a1d9aaae1df728adc7041a8b8b605692140',
'net.java.dev.jna:jna-platform:5.8.0:jna-platform-5.8.0.jar:ffd93fe1bc07de6f33eabf3d051c3636e01a01c17cb0da8448c53a2ac5e3bf7a',
'net.java.dev.jna:jna:5.8.0:jna-5.8.0.jar:930273cc1c492f25661ea62413a6da3fd7f6e01bf1c4dcc0817fc8696a7b07ac',
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'net.jodah:concurrentunit:0.4.2:concurrentunit-0.4.2.jar:5583078e1acf91734939e985bc9e7ee947b0e93a8eef679da6bb07bbeb47ced3',
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
@@ -42,16 +86,22 @@ dependencyVerification {
'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.20:animal-sniffer-ant-tasks-1.20.jar:bb7d2498144118311d968bb08ff6fae3fc535fb1cb9cca8b8e9ea65b189422ac',
'org.codehaus.mojo:animal-sniffer:1.20:animal-sniffer-1.20.jar:80c422523c38db91260c6d78e5ee4b012862ab61cc55020c9e243dd7b5c62249',
'org.eclipse.jetty.alpn:alpn-api:1.1.3.v20160715:alpn-api-1.1.3.v20160715.jar:07be99758b699e194f70fb9784d94202dc6c98212877829e3d72b020f2660576',
'org.fusesource.jansi:jansi:2.4.0:jansi-2.4.0.jar:6cd91991323dd7b2fb28ca93d7ac12af5a86a2f53279e2b35827b30313fd0b9f',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
'org.hsqldb:hsqldb:2.3.5:hsqldb-2.3.5.jar:6676a6977ac98997a80f827ddbd3fe8ca1e0853dad1492512135fd1a222ccfad',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.10:kotlin-stdlib-common-1.4.10.jar:4681f2d436a68c7523595d84ed5758e1382f9da0f67c91e6a848690d711274fe',
'org.jetbrains.kotlin:kotlin-reflect:1.6.21:kotlin-reflect-1.6.21.jar:1e1f57209f7238c3fd1735a1b9339a56565507dca249f8371bf59d91f601aeaa',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.20:kotlin-stdlib-common-1.4.20.jar:a7112c9b3cefee418286c9c9372f7af992bd1e6e030691d52f60cb36dbec8320',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.10:kotlin-stdlib-jdk7-1.4.10.jar:f9566380c08722c780ce33ceee23e98ddf765ca98fabd3e2fabae7975c8d232b',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.10:kotlin-stdlib-jdk8-1.4.10.jar:39b7a9442d7a3865e0f4a732c56c1d5da0e11ffb3bb82a461d32deb0c0ca7673',
'org.jetbrains.kotlin:kotlin-stdlib:1.4.10:kotlin-stdlib-1.4.10.jar:01ecb09782c042b931c1839acf21a188340b295d05400afd6e3415d4475b8daa',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.6.21:kotlin-stdlib-common-1.6.21.jar:183bec59cd9f3a14957b190e8c879cf1194bd1f106b0a7b6e1cbb8790d242363',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.21:kotlin-stdlib-jdk7-1.6.21.jar:f1b0634dbb94172038463020bb2dd45ca26849f8ce29d625acb0f1569d11dbee',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21:kotlin-stdlib-jdk8-1.6.21.jar:dab45489b47736d59fce44b80676f1947a9b6bcab10fd60e878a83bd82a6954c',
'org.jetbrains.kotlin:kotlin-stdlib:1.4.20:kotlin-stdlib-1.4.20.jar:b8ab1da5cdc89cb084d41e1f28f20a42bd431538642a5741c52bbfae3fa3e656',
'org.jetbrains.kotlin:kotlin-stdlib:1.6.21:kotlin-stdlib-1.6.21.jar:739c526672bb337573b28f63afa8306eb088b0c3a0967f56d6c89f4a3012a492',
'org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.2:kotlinx-coroutines-core-jvm-1.6.2.jar:09aac136027678db2d3c2696696202719af9213ba17ae076f4c4421008885bcb',
'org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.6.2:kotlinx-coroutines-jdk8-1.6.2.jar:de9d8adbc78b9ba65bffb44e9dceefb7401ec4c5e9e3f13eb4b5dc0045057aeb',
'org.jetbrains.kotlinx:kotlinx-coroutines-slf4j:1.6.2:kotlinx-coroutines-slf4j-1.6.2.jar:364ac5f09dd941baf460dcc25e95f5ad787db39f36c8c32d508ae961f764effb',
'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.1.0:kotlinx-metadata-jvm-0.1.0.jar:9753bb39efef35957c5c15df9a3cb769aabf2cdfa74b47afcb7760e5146be3b5',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
@@ -62,6 +112,9 @@ dependencyVerification {
'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'org.ow2.asm:asm:9.1:asm-9.1.jar:cda4de455fab48ff0bcb7c48b4639447d4de859a7afc30a094a986f0936beba2',
'org.slf4j:slf4j-api:1.7.36:slf4j-api-1.7.36.jar:d3ef575e3e4979678dc01bf1dcce51021493b4d11fb7f1be8ad982877c16a1c0',
'org.whispersystems:curve25519-java:0.5.0:curve25519-java-0.5.0.jar:0aadd43cf01d11e9b58f867b3c4f25c3194e8b0623d1953d32dfbfbee009e38d',
'org:briarproject:mailbox-core:mailbox-core-0.1.jar:84a843d7ec4486008f57f2e2d13f4048f740a71b75c2f7140defcd54de799c3c',
'org:briarproject:mailbox-lib:mailbox-lib-0.1.jar:7a4cb7a796facce81bc7969c405092be097fafd927108fc29c73ea46d0ab3365',
]
}

View File

@@ -6,7 +6,6 @@ apply plugin: 'idea'
apply plugin: 'witness'
apply from: 'witness.gradle'
apply from: '../dagger.gradle'
apply plugin: 'checkstyle'
configurations {
tor

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble;
import org.briarproject.bramble.io.DnsModule;
import org.briarproject.bramble.network.JavaNetworkModule;
import org.briarproject.bramble.plugin.tor.CircumventionModule;
import org.briarproject.bramble.socks.SocksModule;
@@ -10,7 +9,6 @@ import dagger.Module;
@Module(includes = {
CircumventionModule.class,
DnsModule.class,
JavaNetworkModule.class,
JavaSystemModule.class,
SocksModule.class

View File

@@ -9,8 +9,6 @@ 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.TorControlPort;
import org.briarproject.bramble.api.plugin.TorSocksPort;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils;
@@ -44,6 +42,8 @@ import static java.util.Collections.singletonList;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_CONTROL_PORT;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_SOCKS_PORT;
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.DEFAULT_OBFS4;
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.MEEK;
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.NON_DEFAULT_OBFS4;
@@ -89,6 +89,9 @@ public class BridgeTest extends BrambleTestCase {
private final static long MEEK_TIMEOUT = MINUTES.toMillis(6);
private final static int UNREACHABLE_BRIDGES_ALLOWED = 6;
private final static int ATTEMPTS_PER_BRIDGE = 5;
// Use different ports from Briar Desktop to avoid conflicts
private final static int SOCKS_PORT = DEFAULT_SOCKS_PORT + 10;
private final static int CONTROL_PORT = DEFAULT_CONTROL_PORT + 10;
private final static Logger LOG = getLogger(BridgeTest.class.getName());
@@ -112,12 +115,6 @@ public class BridgeTest extends BrambleTestCase {
Clock clock;
@Inject
CryptoComponent crypto;
@Inject
@TorSocksPort
int torSocksPort;
@Inject
@TorControlPort
int torControlPort;
private final File torDir = getTestDirectory();
private final Params params;
@@ -170,8 +167,8 @@ public class BridgeTest extends BrambleTestCase {
factory = new UnixTorPluginFactory(ioExecutor, wakefulIoExecutor,
networkManager, locationUtils, eventBus, torSocketFactory,
backoffFactory, resourceProvider, bridgeProvider,
batteryManager, clock, crypto, torDir, torSocksPort,
torControlPort);
batteryManager, clock, crypto, torDir,
SOCKS_PORT, CONTROL_PORT);
}
@After

View File

@@ -14,8 +14,7 @@ import dagger.Component;
@Component(modules = {
BrambleCoreIntegrationTestModule.class,
BrambleCoreModule.class,
BrambleJavaModule.class,
TestTorPortsModule.class
BrambleJavaModule.class
})
public interface BrambleJavaIntegrationTestComponent
extends BrambleCoreIntegrationTestEagerSingletons {

View File

@@ -1,26 +0,0 @@
package org.briarproject.bramble.test;
import org.briarproject.bramble.api.plugin.TorControlPort;
import org.briarproject.bramble.api.plugin.TorSocksPort;
import dagger.Module;
import dagger.Provides;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_CONTROL_PORT;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_SOCKS_PORT;
@Module
class TestTorPortsModule {
@Provides
@TorSocksPort
int provideTorSocksPort() {
return DEFAULT_SOCKS_PORT + 10;
}
@Provides
@TorControlPort
int provideTorControlPort() {
return DEFAULT_CONTROL_PORT + 10;
}
}

View File

@@ -1,10 +1,6 @@
apply plugin: 'com.android.application'
apply plugin: 'witness'
apply from: 'witness.gradle'
apply plugin: 'checkstyle'
// Need to manually apply this as the Java plugin is not applied to this module hence this is not
// done automatically.
apply from: "${rootProject.rootDir}/gradle/checkstyle.gradle"
def getStdout = { command, defaultValue ->
def stdout = new ByteArrayOutputStream()
@@ -30,8 +26,8 @@ android {
defaultConfig {
minSdkVersion 16
targetSdkVersion 30
versionCode 10411
versionName "1.4.11"
versionCode 10410
versionName "1.4.10"
applicationId "org.briarproject.briar.android"
buildConfigField "String", "TorVersion", "\"$tor_version\""

View File

@@ -3,7 +3,6 @@ package org.briarproject.briar.android.mailbox;
import android.os.Bundle;
import android.view.MenuItem;
import android.widget.ProgressBar;
import android.widget.Toast;
import org.briarproject.bramble.api.mailbox.MailboxPairingState;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
@@ -24,7 +23,6 @@ import androidx.lifecycle.ViewModelProvider;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static android.widget.Toast.LENGTH_LONG;
import static org.briarproject.briar.android.util.UiUtils.showFragment;
@MethodsNotNullByDefault
@@ -217,8 +215,6 @@ public class MailboxActivity extends BriarActivity {
dialog -> supportFinishAfterTransition());
builder.show();
} else {
Toast.makeText(this, R.string.mailbox_status_unlink_success,
LENGTH_LONG).show();
supportFinishAfterTransition();
}
}

View File

@@ -1,8 +1,5 @@
package org.briarproject.briar.android.reporting;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -13,7 +10,6 @@ import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
@@ -21,9 +17,6 @@ import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.settings.AboutFragment;
import java.util.logging.Logger;
import javax.inject.Inject;
@@ -34,19 +27,14 @@ import androidx.recyclerview.widget.RecyclerView;
import static android.view.View.GONE;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static android.widget.Toast.LENGTH_LONG;
import static android.widget.Toast.LENGTH_SHORT;
import static java.util.Objects.requireNonNull;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class ReportFormFragment extends BaseFragment {
public final static String TAG = ReportFormFragment.class.getName();
private static final Logger LOG = getLogger(TAG);
@Inject
ViewModelProvider.Factory viewModelFactory;
@@ -55,7 +43,6 @@ public class ReportFormFragment extends BaseFragment {
private EditText userCommentView;
private EditText userEmailView;
private TextView privacyPolicy;
private CheckBox includeDebugReport;
private Button chevron;
private RecyclerView list;
@@ -86,7 +73,6 @@ public class ReportFormFragment extends BaseFragment {
userCommentView = v.findViewById(R.id.user_comment);
userEmailView = v.findViewById(R.id.user_email);
privacyPolicy = v.findViewById(R.id.PrivacyPolicy);
includeDebugReport = v.findViewById(R.id.include_debug_report);
chevron = v.findViewById(R.id.chevron);
list = v.findViewById(R.id.list);
@@ -104,19 +90,6 @@ public class ReportFormFragment extends BaseFragment {
userCommentView.setHint(R.string.describe_crash);
}
privacyPolicy.setOnClickListener(View -> {
String url = "https://briarproject.org/privacy-policy/";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
try {
startActivity(i);
} catch (ActivityNotFoundException e) {
logException(LOG, WARNING, e);
Toast.makeText(requireContext(),
R.string.error_start_activity, LENGTH_LONG).show();
}
});
chevron.setOnClickListener(view -> {
boolean show = chevron.getText().equals(getString(R.string.show));
viewModel.showReportData(show);

View File

@@ -38,7 +38,6 @@ public class AboutFragment extends Fragment {
private TextView briarWebsite;
private TextView briarSourceCode;
private TextView briarChangelog;
private TextView briarPrivacyPolicy;
@Nullable
@Override
@@ -62,8 +61,6 @@ public class AboutFragment extends Fragment {
briarWebsite = requireActivity().findViewById(R.id.BriarWebsite);
briarSourceCode = requireActivity().findViewById(R.id.BriarSourceCode);
briarChangelog = requireActivity().findViewById(R.id.BriarChangelog);
briarPrivacyPolicy =
requireActivity().findViewById(R.id.BriarPrivacyPolicy);
briarWebsite.setOnClickListener(View -> {
String url = "https://briarproject.org/";
goToUrl(url);
@@ -77,11 +74,6 @@ public class AboutFragment extends Fragment {
"https://code.briarproject.org/briar/briar/-/wikis/changelog";
goToUrl(url);
});
briarPrivacyPolicy.setOnClickListener(View -> {
String url =
"https://briarproject.org/privacy-policy/";
goToUrl(url);
});
}
private void goToUrl(String url) {

View File

@@ -16,48 +16,48 @@ import androidx.annotation.UiThread;
public class QrCodeView extends FrameLayout {
private final ImageView qrCodeImageView;
private boolean fullscreen = false;
private FullscreenListener listener;
private final ImageView qrCodeImageView;
private boolean fullscreen = false;
private FullscreenListener listener;
public QrCodeView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.qr_code_view, this, true);
qrCodeImageView = findViewById(R.id.qr_code);
ImageView fullscreenButton = findViewById(R.id.fullscreen_button);
fullscreenButton.setOnClickListener(v -> {
fullscreen = !fullscreen;
if (!fullscreen) {
fullscreenButton.setImageResource(
R.drawable.ic_fullscreen_black_48dp);
} else {
fullscreenButton.setImageResource(
R.drawable.ic_fullscreen_exit_black_48dp);
}
if (listener != null)
listener.setFullscreen(fullscreen);
}
);
}
public QrCodeView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.qr_code_view, this, true);
qrCodeImageView = findViewById(R.id.qr_code);
ImageView fullscreenButton = findViewById(R.id.fullscreen_button);
fullscreenButton.setOnClickListener(v -> {
fullscreen = !fullscreen;
if (!fullscreen) {
fullscreenButton.setImageResource(
R.drawable.ic_fullscreen_black_48dp);
} else {
fullscreenButton.setImageResource(
R.drawable.ic_fullscreen_exit_black_48dp);
}
if (listener != null)
listener.setFullscreen(fullscreen);
}
);
}
@UiThread
public void setQrCode(Bitmap qrCode) {
qrCodeImageView.setImageBitmap(qrCode);
// Simple fade-in animation
AlphaAnimation anim = new AlphaAnimation(0.0f, 1.0f);
anim.setDuration(200);
qrCodeImageView.startAnimation(anim);
}
@UiThread
public void setQrCode(Bitmap qrCode) {
qrCodeImageView.setImageBitmap(qrCode);
// Simple fade-in animation
AlphaAnimation anim = new AlphaAnimation(0.0f, 1.0f);
anim.setDuration(200);
qrCodeImageView.startAnimation(anim);
}
@UiThread
public void setFullscreenListener(FullscreenListener listener) {
this.listener = listener;
}
@UiThread
public void setFullscreenListener(FullscreenListener listener) {
this.listener = listener;
}
public interface FullscreenListener {
void setFullscreen(boolean fullscreen);
}
public interface FullscreenListener {
void setFullscreen(boolean fullscreen);
}
}

View File

@@ -60,15 +60,6 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/BriarSourceCode" />
<TextView
android:id="@+id/BriarPrivacyPolicy"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/briar_privacy_policy"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/BriarChangelog" />
<TextView
android:id="@+id/TranslatorThanks"
android:layout_width="match_parent"
@@ -77,6 +68,6 @@
android:text="@string/translator_thanks"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/BriarPrivacyPolicy" />
app:layout_constraintTop_toBottomOf="@+id/BriarChangelog" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -56,18 +56,6 @@
</com.google.android.material.textfield.TextInputLayout>
<TextView
android:id="@+id/PrivacyPolicy"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/margin_large"
android:layout_marginRight="@dimen/margin_large"
android:layout_marginTop="@dimen/margin_large"
android:text="@string/privacy_policy"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/user_email_layout" />
<CheckBox
android:id="@+id/include_debug_report"
android:layout_width="0dp"
@@ -86,10 +74,9 @@
style="@style/BriarButtonFlat.Positive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_medium"
android:text="@string/show"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/PrivacyPolicy" />
app:layout_constraintTop_toBottomOf="@+id/user_email_layout" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"

View File

@@ -26,7 +26,6 @@
<string name="dnkm_xiaomi_button">Предпазване на Briar</string>
<string name="dnkm_xiaomi_help">Ако Briar не е заключен в списъка с последно използваните приложения, няма да работи на заден план.</string>
<string name="dnkm_xiaomi_dialog_body_old">1. Отворете списъка с отворени приложения (списък за превключване на приложения)\n\n2. Плъзнете надолу върху изображението на Briar докато се покаже икона на катинар\n\n3. Ако катинарът е отключен го докоснете, за да го заключите</string>
<string name="dnkm_xiaomi_dialog_body_new">1. Отворете списъка с последните приложения\n\n2. Ако до името на Briar има значка на катинарче, не е необходимо да правите нищо\n\n3. Ако няма натиснете и задръжте изображението на Briar, докато се появи бутон за катинарче, след което го докоснете</string>
<string name="dnkm_warning_dozed_1">Briar не може да работи във фонов режим</string>
<!--Login-->
<string name="enter_password">Парола</string>
@@ -136,7 +135,7 @@
<string name="accept">Приемане</string>
<string name="decline">Отказване</string>
<string name="online">На линия</string>
<string name="offline">Не е свързано</string>
<string name="offline">Извън линия</string>
<string name="send">Изпращане</string>
<string name="allow">Разрешаване</string>
<string name="open">Отваряне</string>
@@ -295,11 +294,6 @@
<string name="different_person_button">Не</string>
<string name="duplicate_link_dialog_text_3">%1$s и %2$s са изпратили еднакви препратки.\n\nЕдиният от двамата вероятно се опитва да разбере кои са контактите ви.\n\nНе им споделяйте, че сте получили същата препратка от друг човек.</string>
<string name="pending_contact_updated_toast">Обновена чакаща заявка за контакт</string>
<!--Peer trust levels-->
<string name="peer_trust_level_unverified">Непроверен контакт</string>
<string name="peer_trust_level_verified">Проверен контакт</string>
<string name="peer_trust_level_ourselves">Аз</string>
<string name="peer_trust_level_stranger">Непознат</string>
<!--Introductions-->
<string name="introduction_onboarding_title">Запознаване на контакти</string>
<string name="introduction_onboarding_text">Можете да запознавате контактите си един с друг, за да се свържат в Briar.</string>
@@ -598,9 +592,7 @@
<string name="mailbox_setup_camera_error_description">Няма достъп до камерата. Опитайте отново и след рестарт на усройството.</string>
<string name="mailbox_setup_paired_title">Свързан</string>
<string name="mailbox_setup_paired_description">Пощенската кутия е свързана с Briar.\n\nЗа да е винаги на линия, я дръжте включена в захранване и свързана с безжична мрежа.</string>
<string name="tor_offline_title">Не е свързано</string>
<string name="tor_offline_description">Уверете се, че устройството е свързано с интернет.\n
\nСлед това изчакайте иконата на земното кълбо в екрана за настройки на връзката да стане зелена.</string>
<string name="tor_offline_title">Извън линия</string>
<string name="tor_offline_button_check">Проверете настройките на връзката</string>
<string name="mailbox_status_title">Състояние на пощенаската кутия</string>
<string name="mailbox_status_connected_title">Пощенската кутия работи</string>
@@ -615,41 +607,12 @@
<string name="mailbox_status_connected_info">Последно свързване: %s</string>
<!--Indicates that there never was a connection to the mailbox. Last connection: Never-->
<string name="mailbox_status_connected_never">Никога</string>
<string name="mailbox_status_unlink_button">Прекъсване на връзката</string>
<string name="mailbox_status_unlink_dialog_title">Желаете ли да прекъснете връзката с пощенската кутия?</string>
<string name="mailbox_status_unlink_button">Прекъсване на връзка</string>
<string name="mailbox_status_unlink_dialog_title">Ще прекъснете ли връзката с пощенската кутия?</string>
<string name="mailbox_status_unlink_dialog_question">Сигурни ли сте, че желаете да прекъснете връзката с пощенската кутия?</string>
<string name="mailbox_status_unlink_dialog_warning">Ако прекъснете връзката с пощенската кутия, няма да получавате съобщения докато Briar е без мрежа.</string>
<string name="mailbox_status_unlink_no_wipe_title">Връзката с пощенската кутия е прекъсната</string>
<string name="mailbox_status_unlink_no_wipe_message">За да завършите процеса, следващия път, когато имате достъп до устройството с пощенската кутия, отворете приложението на пощенската кутия и докоснете бутона „Прекъсване на връзката“.\n\nДаже и вече нямате достъп до устройството с пощенската кутия - не се притеснявайте. Вашата информация е шифрована, така че ще остане защитена, дори и да не завършите този процес.</string>
<string name="mailbox_error_notification_channel_title">Проблем с пощенската кутия на Briar</string>
<string name="mailbox_error_notification_title">Пощенската кутия на Briar не е достъпна</string>
<string name="mailbox_error_notification_text">Докоснете за отстраняване на проблема.</string>
<string name="mailbox_error_wizard_button">Отстраняване на проблема</string>
<string name="mailbox_error_wizard_title">Помощник за отстраняване на неизправнисти на Briar</string>
<string name="mailbox_error_wizard_question1">Имате ли достъп до устройството с пощенската кутия?</string>
<string name="mailbox_error_wizard_answer1">Да, в момента имам.</string>
<string name="mailbox_error_wizard_answer2">В момента не, но по-късно ще имам.</string>
<string name="mailbox_error_wizard_answer3">Не, вече нямам достъп до него.</string>
<string name="mailbox_error_wizard_info1_1">Проверете да ли устройството с пощенската кутия е включено и има връзка с интернет.</string>
<string name="mailbox_error_wizard_question1_1">Отворете приложението за пощенска кутия. Какво виждате?</string>
<string name="mailbox_error_wizard_answer1_1">Виждам инструкциите за настройка на пощенска кутия</string>
<string name="mailbox_error_wizard_answer1_2">Виждам код за QR</string>
<string name="mailbox_error_wizard_answer1_3">Виждам „Пощенската кутия работи“</string>
<string name="mailbox_error_wizard_answer1_4">Виждам „Устройството не е свързано“</string>
<string name="mailbox_error_wizard_info1_1_1">Прекъснете връзката с пощенската кутия, чрез бутона отдолу, а след това, за да се свържете отново с нея, следвайте инструкциите.</string>
<string name="mailbox_error_wizard_info_1_1_2">Прекъснете връзката с пощенската кутия, чрез бутона отдолу, а след това, за да се свържете отново с нея, сканирайте кода за QR..</string>
<string name="mailbox_error_wizard_info1_1_3">Използвайте бутона по-долу, за да проверите връзката между Briar и пощенската кутия.\n\n
Ако връзката отново е неуспешна:\n
\u2022 Проверете дали приложенията Пощенска кутия и Briar са последно издание.\n
\u2022 Рестартирайте устройствата с Пощенска кутия и Briar и опитайте отново.</string>
<string name="mailbox_error_wizard_info1_1_4">Проверете дали устройството с пощенска кутия е свързано с интернет.\n\nПроверете дали часовникът на това устройство показва точното време, дата и часови пояс.\n\nПроверете дали приложенията Пощенска кутия и Briar са последно издание.\n\nРестартирайте устройствата с Пощенска кутия и Briar и опитайте отново.</string>
<string name="mailbox_error_wizard_info2">Върнете се на този екран, когато получите достъп до устройството.</string>
<string name="mailbox_error_wizard_info3">Прекъснете връзката с пощенската кутия, чрез бутона отдолу.\n\nСлед като прекъснете връзката със старата пощенска кутия можете да настроите нова по всяко време.</string>
<!--About-->
<string name="about_title">Относно</string>
<string name="links">Препратки</string>
<!--Here translators can add their names or Transifex usernames(eg "Thanks to all the contributors at the Localization Lab, especially Tom, Matthew and Jerry")-->
<string name="translator_thanks">Благодарим на всички сътрудници на Localization Lab</string>
<!--Conversation Settings-->
<string name="disappearing_messages_title">Изчезващи съобщения</string>
<string name="disappearing_messages_explanation_long">При включване, тази настройка прави бъдещите съобщения в този разговор да изчезват след 7\u00A0дни.
@@ -767,8 +730,6 @@
<string name="website_download_outro">След като файлът бъде изтеглен, го отворете и го инсталирайте.</string>
<string name="website_troubleshooting_title">Отстраняване на неизправности</string>
<string name="website_troubleshooting_1">Ако не можете да изтеглите приложението пробвайте с друг мрежов четец.</string>
<string name="website_troubleshooting_2_old">За да инсталирате изтегленото приложение, може да се наложи да разрешите инсталирането на приложения от „Неизвестни източници“ в системните настройки. След това може да се наложи да изтеглите приложението отново. Препоръчваме ви да изключете настройката \"Неизвестни източници\", след като инсталирате приложението.</string>
<string name="website_troubleshooting_2_new">За да инсталирате изтегленото приложение, може да се наложи да разрешите на мрежовия си четец да инсталира непознати приложения. След като инсталирате приложението, ви препоръчваме да премахнете разрешението за инсталиране на неизвестни приложения.</string>
<string name="hotspot_help_wifi_title">Проблеми при свързване чрез Wi-Fi:</string>
<string name="hotspot_help_wifi_1">Изключете и включете Wi-Fi и на двете устройства, и опитайте отново.</string>
<string name="hotspot_help_wifi_2">Ако устройството се оплаква, че безжичната мрежа няма достъп до интернет, останете свързани въпреки това.</string>
@@ -789,7 +750,6 @@
<string name="hotspot_error_start_callback_failed_unknown">Безжичната точка не може да стартира поради неизвестна грешка: причината е %d</string>
<string name="hotspot_error_start_callback_no_group_info">Безжичната точка не може да стартира: няма информация за група</string>
<string name="hotspot_error_web_server_start">Грешка при стартиране на уеб сървър</string>
<string name="hotspot_error_web_server_serve">Грешка при показване на страницата.n\nАко проблемът продължи да се появява, изпратете обратна връзка (с анонимизирани данни) през приложението Briar.</string>
<string name="hotspot_flag_test">Внимание: Това приложение е инсталирано с Android Studio и НЕ може да бъде инсталирано на друго устройство.</string>
<string name="hotspot_error_framework_busy">Безжичната точка не може да бъде стартирана.\n\nАко има включена друга безжична точка за достъп или споделяте мобилните си данни по безжичен път, опитайте да ги спрете и пробвайте отново.</string>
<!--Transfer Data via Removable Drives-->

View File

@@ -297,11 +297,6 @@
<string name="different_person_button">Andere Person</string>
<string name="duplicate_link_dialog_text_3">%1$s und %2$s haben dir denselben Link geschickt.\n\nMöglicherweise versucht einer der beiden mehr über deine Kontakte zu erfahren.\n\nDu solltest deswegen niemandem sagen, dass du diesen Link auch von jemand anderem erhalten hast.</string>
<string name="pending_contact_updated_toast">Ausstehender Kontakt aktualisiert</string>
<!--Peer trust levels-->
<string name="peer_trust_level_unverified">Nicht überprüfter Kontakt</string>
<string name="peer_trust_level_verified">Überprüfter Kontakt</string>
<string name="peer_trust_level_ourselves">Ich</string>
<string name="peer_trust_level_stranger">Fremder</string>
<!--Introductions-->
<string name="introduction_onboarding_title">Mache deine Kontakte untereinander bekannt</string>
<string name="introduction_onboarding_text">Stelle deine Kontakte einander vor, damit sie miteinander über Briar in Kontakt treten können.</string>
@@ -649,16 +644,6 @@
<string name="mailbox_error_wizard_info1_1_4">Überprüfe, ob das Mailbox-Gerät ordnungsgemäß mit dem Internet verbunden ist.\n\nÜberprüfe, ob die Uhr auf dem Mailbox-Gerät die richtige Uhrzeit, das richtige Datum und die richtige Zeitzone anzeigt.\n\nÜberprüfe, ob die Mailbox- und Briar-Apps auf die neueste Version aktualisiert sind.\n\nStarte deine Mailbox- und Briar-Geräte neu und versuche es erneut.</string>
<string name="mailbox_error_wizard_info2">Bitte rufe diesen Bildschirm wieder auf, wenn du Zugriff auf das Gerät hast.</string>
<string name="mailbox_error_wizard_info3">Bitte trenne die Verknüpfung deiner Mailbox über die Schaltfläche unten.\n\nNach der Trennung deiner alten Mailbox kannst du jederzeit eine neue Mailbox einrichten.</string>
<!--About-->
<string name="about_title">Über</string>
<string name="briar_version">Briar Version: %s</string>
<string name="tor_version">Tor Version: %s</string>
<string name="links">Links</string>
<string name="briar_website">\u2022 <a href="">Webseite</a></string>
<string name="briar_source_code">\u2022 <a href="">Quellcode</a></string>
<string name="briar_changelog">\u2022 <a href="">Changelog</a></string>
<!--Here translators can add their names or Transifex usernames(eg "Thanks to all the contributors at the Localization Lab, especially Tom, Matthew and Jerry")-->
<string name="translator_thanks">Dank an alle Mitwirkenden des Localization Lab</string>
<!--Conversation Settings-->
<string name="disappearing_messages_title">Selbstlöschende Nachrichten</string>
<string name="disappearing_messages_explanation_long">Wenn diese Einstellung aktiviert ist, werden neue
@@ -802,7 +787,7 @@
<string name="hotspot_error_start_callback_failed_unknown">Hotspot konnte aus einem unbekannten Grund nicht gestartet werden, Grund %d</string>
<string name="hotspot_error_start_callback_no_group_info">Hotspot konnte nicht gestartet werden: keine Gruppeninformation</string>
<string name="hotspot_error_web_server_start">Fehler beim Starten des Webservers</string>
<string name="hotspot_error_web_server_serve">Fehler bei der Darstellung der Webseite.\n\nBitte sende eine Rückmeldung (mit anonymen Daten) über die Briar-App, wenn das Problem weiterhin besteht.</string>
<string name="hotspot_error_web_server_serve">Fehler bei der Darstellung der Website.\n\nBitte sende eine Rückmeldung (mit anonymen Daten) über die Briar-App, wenn das Problem weiterhin besteht.</string>
<string name="hotspot_flag_test">Warnung: Diese App wurde mit Android Studio installiert und kann NICHT auf einem anderen Gerät installiert werden.</string>
<string name="hotspot_error_framework_busy">Hotspot kann nicht gestartet werden.\n\nWenn du einen anderen Hotspot betreibst oder deine Internetverbindung über WLAN teilst, beende dies und versuche es danach erneut.</string>
<!--Transfer Data via Removable Drives-->

View File

@@ -301,8 +301,6 @@
<string name="different_person_button">Diferente Persona</string>
<string name="duplicate_link_dialog_text_3">%1$s y %2$s te enviaron el mismo enlace.\n\nUno de ellos puede estar tratando de descubrir quiénes son tus contactos.\n\nNo les digas que recibiste el mismo enlace de otra persona.</string>
<string name="pending_contact_updated_toast">Contacto pendiente actualizado</string>
<!--Peer trust levels-->
<string name="peer_trust_level_ourselves">Yo</string>
<!--Introductions-->
<string name="introduction_onboarding_title">Presenta a tus contactos</string>
<string name="introduction_menu_item">Hacer presentación</string>
@@ -619,10 +617,6 @@
<!--Indicates that there never was a connection to the mailbox. Last connection: Never-->
<string name="mailbox_status_connected_never">Nunca</string>
<string name="mailbox_status_unlink_button">Desvincular</string>
<!--About-->
<string name="about_title">Acerca de</string>
<string name="links">Enlaces</string>
<!--Here translators can add their names or Transifex usernames(eg "Thanks to all the contributors at the Localization Lab, especially Tom, Matthew and Jerry")-->
<!--Conversation Settings-->
<string name="disappearing_messages_title">Mensajes con caducidad</string>
<string name="disappearing_messages_explanation_long">Activar este ajuste hará que los nuevos

View File

@@ -307,11 +307,6 @@
<string name="different_person_button">شخص متفاوت</string>
<string name="duplicate_link_dialog_text_3">%1$s و %2$s یک پیوند یکسان را به شما ارسال کردند.\n\nشاید یکی از آن‌ها قصد شناسایی مخاطبین شما را دارد.\n\nبه آن‌ها نگویید که همان لینک را از فرد دیگری نیز دریافت کرده‌اید.</string>
<string name="pending_contact_updated_toast">مخاطب معلق به روز رسانی شد</string>
<!--Peer trust levels-->
<string name="peer_trust_level_unverified">مخاطب تایید نشده</string>
<string name="peer_trust_level_verified">مخاطب تایید شده</string>
<string name="peer_trust_level_ourselves">من</string>
<string name="peer_trust_level_stranger">غریبه</string>
<!--Introductions-->
<string name="introduction_onboarding_title">معرفی مخاطبان</string>
<string name="introduction_onboarding_text">مخاطبین خود را به یکدیگر معرفی کنید تا بتوانند در Briar متصل شوند.</string>
@@ -681,16 +676,6 @@
<string name="mailbox_error_wizard_info1_1_4">بررسی کنید که دستگاه Mailbox به درستی به اینترنت متصل باشد.\n\nبررسی کنید که ساعت در دستگاه Mailbox زمان، تاریخ و منطقه زمانی مناسب را نشان دهد.\n\nبررسی کنید که برنامه‌های Mailbox و Briar به آخرین نسخه به‌روزرسانی شده باشند. \n\nدستگاههای Mailbox و Briar خود را راه‌اندازی مجدد کنید و دوباره امتحان کنید.</string>
<string name="mailbox_error_wizard_info2">لطفا هنگامی که به دستگاه دسترسی دارید به این صفحه بازگردید.</string>
<string name="mailbox_error_wizard_info3">لطفا با استفاده از دکمه زیر، پیوند Mailbox خود را لغو کنید.\n\nپس از لغو پیوند Mailbox قدیمی، می‌توانید هر زمان که خواستید یک Mailbox جدید راه‌اندازی کنید.</string>
<!--About-->
<string name="about_title">درباره‌ی Psiphon</string>
<string name="briar_version">نسخه Briar: %s</string>
<string name="tor_version">نسخه Tor: %s</string>
<string name="links">لینک ها</string>
<string name="briar_website">\u2022 <a href="">وبسایت</a></string>
<string name="briar_source_code">\u2022 <a href="">کد منبع</a></string>
<string name="briar_changelog">\u2022 <a href="">گزارش تغییرات</a></string>
<!--Here translators can add their names or Transifex usernames(eg "Thanks to all the contributors at the Localization Lab, especially Tom, Matthew and Jerry")-->
<string name="translator_thanks">با تشکر از همه مشارکت کنندگان در Localization Lab بخصوص erinm، Reza Ghasemi، Mohsen Eghbal و Vox.</string>
<!--Conversation Settings-->
<string name="disappearing_messages_title">پیام‌های ناپدید شونده</string>
<string name="disappearing_messages_explanation_long">روشن کردن این تنظیمات موجب خواهد شد تا پیام‌های جدید

View File

@@ -301,7 +301,6 @@
<string name="different_person_button">Une personne différente</string>
<string name="duplicate_link_dialog_text_3">%1$s et %2$s vous ont envoyé le même lien.\n\nL\'une de ces personnes pourrait tenter de découvrir qui sont vos contacts.\n\nNe lui dites pas que vous avez reçu le même lien de quelquun dautre.</string>
<string name="pending_contact_updated_toast">Le contact en attente a été mis à jour</string>
<!--Peer trust levels-->
<!--Introductions-->
<string name="introduction_onboarding_title">Présenter vos contacts</string>
<string name="introduction_onboarding_text">Présentez vos contacts l\'un à l\'autre ainsi ils pourront se contacter via Briar.</string>
@@ -612,10 +611,6 @@
<!--Example for string substitution: Last connection: 3min ago-->
<!--Indicates that there never was a connection to the mailbox. Last connection: Never-->
<string name="mailbox_status_connected_never">Jamais</string>
<!--About-->
<string name="about_title">À propos</string>
<string name="links">Liens</string>
<!--Here translators can add their names or Transifex usernames(eg "Thanks to all the contributors at the Localization Lab, especially Tom, Matthew and Jerry")-->
<!--Conversation Settings-->
<string name="disappearing_messages_title">Messages éphémères</string>
<string name="disappearing_messages_explanation_long">Lactivation de ce paramètre fera disparaître

View File

@@ -291,7 +291,6 @@
<string name="different_person_button">Annar einstaklingur</string>
<string name="duplicate_link_dialog_text_3">%1$s og %2$s sendu þér sama tengilinn.\n\nAnnar þeirra gæti verið að reyna að finna út hverjir tengiliðirnir þínir eru.\n\nEkki segja þeim að þú hafir fengið sama tengil frá einhverjum öðrum.</string>
<string name="pending_contact_updated_toast">Tengiliður í bið uppfærður</string>
<!--Peer trust levels-->
<!--Introductions-->
<string name="introduction_onboarding_title">Kynntu tengiliðina þína</string>
<string name="introduction_menu_item">Útbúa kynningu</string>
@@ -604,10 +603,6 @@
<!--Indicates that there never was a connection to the mailbox. Last connection: Never-->
<string name="mailbox_status_connected_never">Aldrei</string>
<string name="mailbox_status_unlink_button">Aftengja</string>
<!--About-->
<string name="about_title">Um hugbúnaðinn</string>
<string name="links">Hlekkir</string>
<!--Here translators can add their names or Transifex usernames(eg "Thanks to all the contributors at the Localization Lab, especially Tom, Matthew and Jerry")-->
<!--Conversation Settings-->
<string name="disappearing_messages_title">Sjálfeyðandi skilaboð</string>
<string name="disappearing_messages_explanation_long">Ef kveikt er á þessari stillingu munu ný

View File

@@ -284,11 +284,6 @@
<string name="different_person_button">別の人</string>
<string name="duplicate_link_dialog_text_3">%1$sと%2$sから同じリンクを受信しました。\n\nどちらかがあなたの連絡先の内容を知ろうとしている可能性があります。\n\n他の人から同じリンクを受け取ったことを伝えないでください。</string>
<string name="pending_contact_updated_toast">保留中の連絡先が更新されました</string>
<!--Peer trust levels-->
<string name="peer_trust_level_unverified">検証されてない連絡先</string>
<string name="peer_trust_level_verified">検証された連絡先</string>
<string name="peer_trust_level_ourselves"></string>
<string name="peer_trust_level_stranger">見知らぬ人</string>
<!--Introductions-->
<string name="introduction_onboarding_title">連絡先を紹介</string>
<string name="introduction_onboarding_text">連絡先をお互いに紹介することで、Briarで繋がることができます。</string>
@@ -632,16 +627,6 @@
<string name="mailbox_error_wizard_info1_1_4">メールボックス端末がインターネットに適切に接続されているか、確認してください。\n\nメールボックス端末の時計が正しい時刻、日付、時間帯を表示しているか、確認してください。\n\nメールボックスとBriarアプリが最新版に更新されているか、確認してください。\n\nメールボックスとBriarの端末を再起動し、再度お試しください。</string>
<string name="mailbox_error_wizard_info2">端末にアクセスしたら、この画面に戻って来てください。</string>
<string name="mailbox_error_wizard_info3">以下のボタンを使用してメールボックスをリンク解除してください。\n\n古いメールボックスをリンク解除した後、いつでも新しいメールボックスをセットアップできます。</string>
<!--About-->
<string name="about_title">Tor Project について</string>
<string name="briar_version">Briar バージョン: %s</string>
<string name="tor_version">Tor バージョン: %s</string>
<string name="links">リンク</string>
<string name="briar_website">\u2022 <a href="">ウェブサイト</a></string>
<string name="briar_source_code">\u2022 <a href="">ソースコード</a></string>
<string name="briar_changelog">\u2022 <a href="">変更履歴</a></string>
<!--Here translators can add their names or Transifex usernames(eg "Thanks to all the contributors at the Localization Lab, especially Tom, Matthew and Jerry")-->
<string name="translator_thanks">Localization Labの全貢献者へ感謝</string>
<!--Conversation Settings-->
<string name="disappearing_messages_title">消えるメッセージ</string>
<string name="disappearing_messages_explanation_long">この設定を有効にすると、

View File

@@ -311,7 +311,6 @@
<string name="different_person_button">Kitas asmuo</string>
<string name="duplicate_link_dialog_text_3">%1$s ir %2$s išsiuntė jums tą pačią nuorodą.\n\nGali būti, kad vienas iš šių asmenų bando sužinoti kas yra jūsų adresatų sąraše.\n\nNesakykite šiems asmenims, kad gavote tokią pačią nuorodą iš kito asmens.</string>
<string name="pending_contact_updated_toast">Laukiantis adresatas atnaujintas</string>
<!--Peer trust levels-->
<!--Introductions-->
<string name="introduction_onboarding_title">Supažindinkite savo adresatus</string>
<string name="introduction_menu_item">Supažindinti</string>
@@ -624,10 +623,6 @@
<!--Indicates that there never was a connection to the mailbox. Last connection: Never-->
<string name="mailbox_status_connected_never">Niekada</string>
<string name="mailbox_status_unlink_button">Atsieti</string>
<!--About-->
<string name="about_title">Apie</string>
<string name="links">Nuorodos</string>
<!--Here translators can add their names or Transifex usernames(eg "Thanks to all the contributors at the Localization Lab, especially Tom, Matthew and Jerry")-->
<!--Conversation Settings-->
<string name="disappearing_messages_title">Išnykstančios žinutės</string>
<string name="disappearing_messages_explanation_long">Įjungus šį nustatymą, naujos žinutės
@@ -745,8 +740,6 @@
<string name="hotspot_manual_site_address">Adresas (URL)</string>
<string name="hotspot_qr_site">Jūsų telefonas teikia belaidį (Wi-Fi) prieigos tašką. Žmonės, prisijungę prie prieigos taško, gali atsisiųsti Briar, skenuodami šį QR kodą.</string>
<!--e.g. Download Briar 1.2.20-->
<string name="website_download_title_1">Atsisiųsti Briar %s</string>
<string name="website_download_button">Atsisiųsti Briar</string>
<string name="website_download_outro">Kai atsisiuntimas pasibaigs, atverkite atsisiųstą failą ir jį įdiekite.</string>
<string name="website_troubleshooting_title">Nesklandumų šalinimas</string>
<string name="website_troubleshooting_1">Jei negalite atsisiųsti programėlės, pabandykite naudoti kitą saityno naršyklės programėlę.</string>

View File

@@ -281,8 +281,6 @@
<string name="different_person_button">နောက်တစ်ယောက် </string>
<string name="duplicate_link_dialog_text_3">%1$sနှင့်%2$s တူညီသောလင့်ခ်ကို သင့်အား ပေးပို့ခဲ့သည်။ \n\n သူတို့ထဲမှ တစ်ဦးက သင့်အဆက်အသွယ်များသည် မည်သူဖြစ်သည်ကို ရှာဖွေရန် ကြိုးစားနေပေမည်။ \n\nသင်သည် အခြားသူတစ်ဦးထံမှ တူညီသောလင့်ခ်ကို ရရှိထားကြောင်း ၎င်းတို့အား မပြောပါနှင့်။</string>
<string name="pending_contact_updated_toast">ဆိုင်းငံ့ထားသော အဆက်အသွယ်ကို အပ်ဒိတ်လုပ်ပြီး</string>
<!--Peer trust levels-->
<string name="peer_trust_level_ourselves">ကျွနု်ပ်ကို</string>
<!--Introductions-->
<string name="introduction_onboarding_title">သင့်ရဲ့ အဆက်အသွယ်လိပ်စာများကို မိတ်ဆက်ပါ</string>
<string name="introduction_menu_item">မိတ်ဆက်ခြင်း ပြုလုပ်ပါ</string>
@@ -572,9 +570,6 @@
<!--Example for string substitution: Last connection: 3min ago-->
<!--Indicates that there never was a connection to the mailbox. Last connection: Never-->
<string name="mailbox_status_connected_never">ဘယ်တော့မှ</string>
<!--About-->
<string name="about_title">အကြောင်း</string>
<!--Here translators can add their names or Transifex usernames(eg "Thanks to all the contributors at the Localization Lab, especially Tom, Matthew and Jerry")-->
<!--Conversation Settings-->
<string name="disappearing_messages_title">ပျောက်ကွယ် မက်ဆေ့ချ်များ</string>
<string name="disappearing_messages_explanation_long">၎င်းအပြင်အဆင်ကို ဖွင့်ထားလျှင်

View File

@@ -311,7 +311,6 @@
<string name="different_person_button">Inna osoba</string>
<string name="duplicate_link_dialog_text_3">%1$si %2$s wysłał ci ten sam link.\n\nJeden z nich może próbować odkryć, kim są twoje kontakty.\n\nNie mów im, że otrzymałeś ten sam link od kogoś innego.</string>
<string name="pending_contact_updated_toast">Oczekujący kontakt zaktualizowany</string>
<!--Peer trust levels-->
<!--Introductions-->
<string name="introduction_onboarding_title">Przedstaw swoje kontakty.</string>
<string name="introduction_onboarding_text">Przedstaw kontakty sobie nawzajem, aby mogły się połączyć w Briar.</string>
@@ -646,10 +645,6 @@ Brak dostępu do aparatu. Spróbuj ponownie, może po ponownym uruchomieniu urz
<string name="mailbox_error_wizard_answer1">Tak, mam teraz dostęp</string>
<string name="mailbox_error_wizard_answer2">Nie w tej chwili, ale będę miał(a) dostęp później</string>
<string name="mailbox_error_wizard_answer3">Nie, nie mam już dostępu do urządzenia.</string>
<!--About-->
<string name="about_title">O programie...</string>
<string name="links">Odnośniki</string>
<!--Here translators can add their names or Transifex usernames(eg "Thanks to all the contributors at the Localization Lab, especially Tom, Matthew and Jerry")-->
<!--Conversation Settings-->
<string name="disappearing_messages_title">Znikające wiadomości</string>
<string name="disappearing_messages_explanation_long">Włączenie tego ustawienia spowoduje, że

View File

@@ -301,7 +301,6 @@
<string name="different_person_button">Pessoa diferente</string>
<string name="duplicate_link_dialog_text_3">%1$s e %2$s enviaram o mesmo link para você.\n\nUm deles pode estar tentando descobrir quem são seus contatos.\n\nNão diga a eles que você recebeu o mesmo link de outra pessoa.</string>
<string name="pending_contact_updated_toast">Contato pendente atualizado</string>
<!--Peer trust levels-->
<!--Introductions-->
<string name="introduction_onboarding_title">Apresente seus contatos</string>
<string name="introduction_onboarding_text">Apresente seus contatos entre si para que eles possam se conectar no Briar.</string>
@@ -625,10 +624,6 @@
<string name="mailbox_status_unlink_dialog_warning">Se você desvincular seu Mailbox, você não poderá receber mensagens enquanto o Briar estiver offline.</string>
<string name="mailbox_status_unlink_no_wipe_title">Seu Mailbox foi desvinculado</string>
<string name="mailbox_status_unlink_no_wipe_message">Na próxima vez que você acessar seu dispositivo de Mailbox, por favor, abra o app Mailbox e toque no botão \"Desvincular\" para completar o processo. \n\nSe você não tem mais acesso ao seu dispositivo de Mailbox, não se preocupe. Seus dados estão criptografados, logo, continuarão seguros mesmo que você não complete o processo.</string>
<!--About-->
<string name="about_title">Sobre</string>
<string name="links">Linques</string>
<!--Here translators can add their names or Transifex usernames(eg "Thanks to all the contributors at the Localization Lab, especially Tom, Matthew and Jerry")-->
<!--Conversation Settings-->
<string name="disappearing_messages_title">Mensagens efêmeras</string>
<string name="disappearing_messages_explanation_long">Ativar essa opção fará novas

View File

@@ -259,9 +259,9 @@
<string name="connection_error_title">Не удалось подключиться к контакту</string>
<string name="connection_error_feedback">Если эта проблема сохраняется, пожалуйста <a href="feedback">отправьте отзыв</a>, чтобы помочь нам улучшить приложение.</string>
<!--Adding Contacts Remotely-->
<string name="add_contact_remotely_title_case">Добавление контакта удаленно</string>
<string name="add_contact_remotely_title_case">Добавление контакта на расстоянии</string>
<string name="add_contact_nearby_title">Добавить контакт поблизости</string>
<string name="add_contact_remotely_title"> Добавление контакта удаленно</string>
<string name="add_contact_remotely_title">Добавить контакт на расстоянии</string>
<string name="contact_link_intro">Введите ссылку от вашего контакта здесь</string>
<string name="contact_link_hint">Ссылка контакта</string>
<string name="paste_button">Вставить</string>
@@ -271,7 +271,7 @@
<string name="send_link_title">Обмен ссылками</string>
<string name="add_contact_choose_nickname">Выберите псевдоним</string>
<string name="add_contact_choose_a_nickname">Введите псевдоним</string>
<string name="nickname_intro">Задайте этому контакту псевдоним. Его можете видеть только вы.</string>
<string name="nickname_intro">Дайте вашему контакту псевдоним. Увидеть его сможете только вы.</string>
<string name="your_link">Передайте эту ссылку контакту, который вы хотите добавить.</string>
<string name="link_clip_label">Ссылка Briar</string>
<string name="link_copied_toast">Ссылка скопирована</string>
@@ -317,11 +317,6 @@
<string name="different_person_button">Другой человек</string>
<string name="duplicate_link_dialog_text_3">%1$s и %2$s отправили вам ту же ссылку.\n\nОдин из них, возможно, пытается выяснить, кто ваши контакты.\n\nНе говорите им, что вы получили такую ​​же ссылку от кого-то еще.</string>
<string name="pending_contact_updated_toast">Ожидающий контакт обновлен</string>
<!--Peer trust levels-->
<string name="peer_trust_level_unverified">Неверифицированный контакт</string>
<string name="peer_trust_level_verified">Верифицированный контакт</string>
<string name="peer_trust_level_ourselves">Я</string>
<string name="peer_trust_level_stranger">Незнакомец</string>
<!--Introductions-->
<string name="introduction_onboarding_title">Представление ваших контактов</string>
<string name="introduction_onboarding_text">Представьте ваши контакты друг другу, чтобы они могли общаться на Briar.</string>
@@ -677,16 +672,6 @@
<string name="mailbox_error_wizard_info1_1_4">Убедитесь, что устройство Mailbox корректно подключено к интернету.\n\nУбедитесь, что часы на устройстве Mailbox показывают правильное время, дату и часовой пояс.\n\nУбедитесь, что приложения Mailbox и Briar обновлены до последней версии.\n\nПерезагрузите устройства Mailbox и Briar и повторите попытку.</string>
<string name="mailbox_error_wizard_info2">Пожалуйста, вернитесь к этому экрану, когда у вас будет доступ к устройству.</string>
<string name="mailbox_error_wizard_info3">Пожалуйста, отвяжите свой Mailbox с помощью кнопки ниже.\n\nПосле отсоединения старого Mailbox вы в любое время сможете настроить новый.</string>
<!--About-->
<string name="about_title">О проекте</string>
<string name="briar_version">Версия Briar: %s</string>
<string name="tor_version">Версия Tor: %s</string>
<string name="links">Ссылки</string>
<string name="briar_website">\u2022 <a href="">Сайт</a></string>
<string name="briar_source_code">\u2022 <a href="">Исходный код</a></string>
<string name="briar_changelog">\u2022 <a href="">Список изменений</a></string>
<!--Here translators can add their names or Transifex usernames(eg "Thanks to all the contributors at the Localization Lab, especially Tom, Matthew and Jerry")-->
<string name="translator_thanks">Благодарим всех участников проекта Localization Lab</string>
<!--Conversation Settings-->
<string name="disappearing_messages_title">Исчезающие сообщения</string>
<string name="disappearing_messages_explanation_long">Включение этого параметра приведет к созданию нового

View File

@@ -298,11 +298,6 @@ dhe smund të hapet me këtë version.\n\nJu lutemi, përmirësojeni me versi
<string name="different_person_button">Person i Ndryshëm</string>
<string name="duplicate_link_dialog_text_3">%1$s dhe %2$s ju dërguan të njëjtën lidhje.\n\nNjë prej tyre mund të jetë duke u rrekur të zbulojë cilët janë kontaktet tuaja.\n\nMos u thoni se morët të njëjtën lidhje nga dikush tjetër.</string>
<string name="pending_contact_updated_toast">Kontakti pezull u përditësua</string>
<!--Peer trust levels-->
<string name="peer_trust_level_unverified">Kontakt i paverifikuar</string>
<string name="peer_trust_level_verified">Kontakt i verifikuar</string>
<string name="peer_trust_level_ourselves">Unë</string>
<string name="peer_trust_level_stranger">I huaj</string>
<!--Introductions-->
<string name="introduction_onboarding_title">Prezantoni kontaktet tuaja</string>
<string name="introduction_onboarding_text">Prezantoni kontaktet tuaj me njëri-tjetrin, që të mund të lidhen me Briar.</string>
@@ -650,16 +645,6 @@ dhe smund të hapet me këtë version.\n\nJu lutemi, përmirësojeni me versi
<string name="mailbox_error_wizard_info1_1_4">Shihni që pajisja kuti postare të jetë lidhur si duhet në Internet.\n\nKontrolloni që sahati te pajisja Kuti postare shfaq kohën, datën dhe zonën kohore të saktë.\n\nShihni që aplikacionet Kuti postare dhe Briar të jenë të përditësuar me versionin më të ri.\n\nRinisni pajisjet tuaja Kuti postare dhe Briar dhe riprovoni.</string>
<string name="mailbox_error_wizard_info2">Ju lutemi, rikthejuni kësaj skene kur të keni mundësi të përdorni pajisjen.</string>
<string name="mailbox_error_wizard_info3">Ju lutemi, shkëputeni kutinë tuaj postare duke përdorur butonin më poshtë.\n\nPasi të shkëputni Kutinë tuaj të vjetër postare, mund të ujdisni kurdo një Kuti të re postare.</string>
<!--About-->
<string name="about_title">Mbi</string>
<string name="briar_version">Version Briar-i: %s</string>
<string name="tor_version">Version Tor-i: %s</string>
<string name="links">Lidhje</string>
<string name="briar_website">\u2022 <a href="">Sajt</a></string>
<string name="briar_source_code">\u2022 <a href="">Kod burim</a></string>
<string name="briar_changelog">\u2022 <a href="">Regjistër ndryshimesh</a></string>
<!--Here translators can add their names or Transifex usernames(eg "Thanks to all the contributors at the Localization Lab, especially Tom, Matthew and Jerry")-->
<string name="translator_thanks">Faleminderit krejt kontribuesve prej Localization Lab</string>
<!--Conversation Settings-->
<string name="disappearing_messages_title">Mesazhe që treten</string>
<string name="disappearing_messages_explanation_long">Aktivizimi i këtij rregullimi do të bëjë që

View File

@@ -292,7 +292,6 @@ Vänlige installera Briar på en nyare enhet.</string>
<string name="different_person_button">Olika personer</string>
<string name="duplicate_link_dialog_text_3">%1$s och %2$s skickade dig samma länk.\n\nEn av dem kanske försöker ta reda på vilka dina kontakter är.\n\nBerätta inte för dem att du fått samma länk från någon annan.</string>
<string name="pending_contact_updated_toast">Väntande kontakt har uppdaterats</string>
<!--Peer trust levels-->
<!--Introductions-->
<string name="introduction_onboarding_title">Presentera dina kontakter</string>
<string name="introduction_onboarding_text">Introducera dina kontakter för varandra så att de kan ansluta sig till varandra via Briar.</string>
@@ -607,10 +606,6 @@ Vänlige installera Briar på en nyare enhet.</string>
<!--Indicates that there never was a connection to the mailbox. Last connection: Never-->
<string name="mailbox_status_connected_never">Aldrig</string>
<string name="mailbox_status_unlink_button">Avlänka</string>
<!--About-->
<string name="about_title">Om</string>
<string name="links">Länkar</string>
<!--Here translators can add their names or Transifex usernames(eg "Thanks to all the contributors at the Localization Lab, especially Tom, Matthew and Jerry")-->
<!--Conversation Settings-->
<string name="disappearing_messages_title">Försvinnande meddelanden</string>
<string name="disappearing_messages_explanation_long">Att slå på denna inställning kommer att få nya

View File

@@ -291,11 +291,6 @@
<string name="different_person_button">Farklı Kişi</string>
<string name="duplicate_link_dialog_text_3">%1$s ve %2$s size aynı bağlantıyı gönderdi.\n\nAralarından biri kişilerinizin kim olduğunu keşfetmeye çalışıyor olabilir.\n\nOnlara başkasından aynı bağlantıyı aldığınızı söylemeyin.</string>
<string name="pending_contact_updated_toast">Bekleyen kişi güncellendi</string>
<!--Peer trust levels-->
<string name="peer_trust_level_unverified">Doğrulanmamış kişi</string>
<string name="peer_trust_level_verified">Doğrulanmış kişi</string>
<string name="peer_trust_level_ourselves">Benim</string>
<string name="peer_trust_level_stranger">Yabancı</string>
<!--Introductions-->
<string name="introduction_onboarding_title">Kişilerinizi tanıştırın</string>
<string name="introduction_onboarding_text">Kişilerinizi birbirlerine tanıtın, böylece Briar üzerinden bağlantı kurabilirler.</string>
@@ -604,10 +599,6 @@
<string name="mailbox_status_connected_title">Mailbox çalışıyor</string>
<string name="mailbox_status_problem_title">Briar Mailbox\'a bağlantı kurmakta zorluk yaşıyor.</string>
<string name="mailbox_status_failure_title">Mailbox kullanılamıyor</string>
<string name="mailbox_status_app_too_old_title">Briar çok eski</string>
<string name="mailbox_status_app_too_old_message">Briar\'ı uygulamanın son sürümüne güncelleyin ve tekrar deneyin.</string>
<string name="mailbox_status_mailbox_too_old_title">Mailbox çok eski</string>
<string name="mailbox_status_mailbox_too_old_message">Mailbox\'unuzu uygulamanın son sürümüne güncelleyin ve tekrar deneyin.</string>
<string name="mailbox_status_check_button">Bağlantıyı denetle</string>
<!--Example for string substitution: Last connection: 3min ago-->
<string name="mailbox_status_connected_info">Son bağlantı: %s</string>
@@ -619,37 +610,6 @@
<string name="mailbox_status_unlink_dialog_warning">Mailbox bağlantısını kaldırırsanız, Briar çevrimdışı iken ileti alamayacaksınız.</string>
<string name="mailbox_status_unlink_no_wipe_title">Mailbox bağlantısı kaldırıldı.</string>
<string name="mailbox_status_unlink_no_wipe_message">Mailbox aygıtınıza sonraki erişiminizde lütfen Mailbox uygulamasınıın ve \"Bağlantıyı Kaldır\" düğmesine dokunarak işlemi tamamlayın.\n\nEğer Mailbox aygıtınıza artık erişiminiz yoksa endişelenmeyin. Veriniz şifrelenmiştir ve bu süreci tamamlamasanız bile güvenli kalacaktır.</string>
<string name="mailbox_error_notification_channel_title">Briar Mailbox sorunu</string>
<string name="mailbox_error_notification_title">Briar Mailbox kullanılamıyor</string>
<string name="mailbox_error_notification_text">Sorunu çözmek için dokunun</string>
<string name="mailbox_error_wizard_button">Sorunu çöz</string>
<string name="mailbox_error_wizard_title">Mailbox sorun çözme sihirbazı</string>
<string name="mailbox_error_wizard_question1">Mailbox aygıtınıza erişiminiz var mı?</string>
<string name="mailbox_error_wizard_answer1">Evet, şu an ona erişimim var.</string>
<string name="mailbox_error_wizard_answer2">Şimdi değil ama daha sonra erişebilirim.</string>
<string name="mailbox_error_wizard_answer3">Hayır, artık ona erişimim yok.</string>
<string name="mailbox_error_wizard_info1_1">Mailbox aygıtının açık ve İnternet\'e bağlı olduğunu denetleyin.</string>
<string name="mailbox_error_wizard_question1_1">Mailbox uygulamasınıın. Ne görüyorsunuz?</string>
<string name="mailbox_error_wizard_answer1_1">Mailbox kurulumu yönergelerini görüyorum.</string>
<string name="mailbox_error_wizard_answer1_2">Bir Karekod görüyorum.</string>
<string name="mailbox_error_wizard_answer1_3">\"Mailbox çalışıyor\" görüyorum</string>
<string name="mailbox_error_wizard_answer1_4">\"Aygıt çevrimdışı\" görüyorum</string>
<string name="mailbox_error_wizard_info1_1_1">Lütfen Mailbox\'ınızın bağlantısını aşağıdaki düğmeyi kullanarak kesin, daha sonra tekrar bağlamak için Mailbox aygıtındaki yönergeleri izleyin.</string>
<string name="mailbox_error_wizard_info_1_1_2">Lütfen Mailbox\'ınızın bağlantısını aşağıdaki düğmeyi kullanarak kesin, daha sonra tekrar bağlamak için Karekodu tarayın.</string>
<string name="mailbox_error_wizard_info1_1_3">Briar ve Mailbox arasındaki bağlantıyı denetlemek için aşağıdaki düğmeyi kullanın.\n\n
Eğer bağlantı tekrar başarısız olursa:\n
\u2022 Mailbox ve Briar\'ın son sürüme güncellendiğini denetleyin.\n
Mailbox ve Briar aygıtlarını yeniden başlatın ve tekrar deneyin.</string>
<!--About-->
<string name="about_title">Hakkında</string>
<string name="briar_version">Briar sürümü: %s</string>
<string name="tor_version">Tor sürümü: %s</string>
<string name="links">Bağlantılar</string>
<string name="briar_website">\u2022 <a href="">Web Site</a></string>
<string name="briar_source_code">\u2022 <a href="">Kaynak kod</a></string>
<string name="briar_changelog">\u2022 <a href="">Değişiklik günlüğü</a></string>
<!--Here translators can add their names or Transifex usernames(eg "Thanks to all the contributors at the Localization Lab, especially Tom, Matthew and Jerry")-->
<string name="translator_thanks">Localization Lab\'taki tüm katkı sağlayanlara teşekkürler</string>
<!--Conversation Settings-->
<string name="disappearing_messages_title">Kaybolan iletiler</string>
<string name="disappearing_messages_explanation_long">Bu ayarı etkinleştirmeniz durumunda
@@ -765,9 +725,6 @@
<string name="hotspot_manual_site_address">Adres (URL)</string>
<string name="hotspot_qr_site">Telefonunuz bir kablosuz erişim noktası sunuyor. Erişim noktasına bağlı kişiler Briar\'ı QR kodunu tarayarak indirebilirler. </string>
<!--e.g. Download Briar 1.2.20-->
<string name="website_download_title_1">Briar\'ı indir %s</string>
<string name="website_download_intro_1">Yakınlarınızdaki biri sizinle Briar\'ı paylaştı</string>
<string name="website_download_button">Briar\'ı indir</string>
<string name="website_download_outro">İndirme tamamlandıktan sonra, indirdiğiniz dosyayıın ve kurun.</string>
<string name="website_troubleshooting_title">Sorun çözme</string>
<string name="website_troubleshooting_1">Uygulamayı indiremiyorsanız, başka bir tarayıcı uygulamasıyla deneyin.</string>

View File

@@ -311,7 +311,6 @@
<string name="different_person_button">Різні особи</string>
<string name="duplicate_link_dialog_text_3">%1$s та %2$s надіслали вам однакові посилання.\n\nХтось із них, можливо, намагається виявити ваші контакти.\n\nНе кажіть їм, що вже отримували це посилання від когось іще.</string>
<string name="pending_contact_updated_toast">Оновлено нерозглянутий контакт</string>
<!--Peer trust levels-->
<!--Introductions-->
<string name="introduction_onboarding_title">Поділитися своїми контактами</string>
<string name="introduction_onboarding_text">Представте свої контакти навзаєм, щоб вони могли спілкуватись у Briar.</string>
@@ -637,10 +636,6 @@
<string name="mailbox_error_wizard_question1">Ви маєте доступ до вашого пристрою Mailbox?</string>
<string name="mailbox_error_wizard_answer1_1">Я бачу вказівки щодо налаштування Mailbox</string>
<string name="mailbox_error_wizard_answer1_2">Я бачу QR-код</string>
<!--About-->
<string name="about_title">Про</string>
<string name="links">Посилання</string>
<!--Here translators can add their names or Transifex usernames(eg "Thanks to all the contributors at the Localization Lab, especially Tom, Matthew and Jerry")-->
<!--Conversation Settings-->
<string name="disappearing_messages_title">Самознищувані повідомлення</string>
<string name="disappearing_messages_explanation_long">Коли цей параметр увімкнено, нові

View File

@@ -287,11 +287,6 @@
<string name="different_person_button">不同的人</string>
<string name="duplicate_link_dialog_text_3">%1$s 和 %2$s 给你发送了同样的链接。\n\n其中一个人可能企图找出谁是你的联系人。\n\n 不要告诉他们你从其他人那里收到了相同的链接。</string>
<string name="pending_contact_updated_toast">待处理联系人已更新</string>
<!--Peer trust levels-->
<string name="peer_trust_level_unverified">未验证的联系人</string>
<string name="peer_trust_level_verified">已验证的联系人</string>
<string name="peer_trust_level_ourselves"></string>
<string name="peer_trust_level_stranger">陌生人</string>
<!--Introductions-->
<string name="introduction_onboarding_title">介绍您的联系人</string>
<string name="introduction_onboarding_text">向你的联系人互相介绍彼此,这样他们可以在 Briar 上建立联系</string>
@@ -635,16 +630,6 @@
<string name="mailbox_error_wizard_info1_1_4">检查装有 Mailbox 的设备是否已正确连接到互联网。\n\n检查装有 Mailboxde 设备上的时钟是否显示正确的时间、日期和时区。\n\n检查 Mailbox 和 Briar 应用是否更新到最新版本。\n\n重新启动装有 Mailbox 和Briar 应用的设备,然后重试。</string>
<string name="mailbox_error_wizard_info2">当你可以使用该设备时,请回到此屏幕。</string>
<string name="mailbox_error_wizard_info3">请使用下面的按钮取消你的 Mailbox 链接。\n\n在取消对旧 Mailbox 的链接后,你可以随时设置一个新的 Mailbox。</string>
<!--About-->
<string name="about_title">关于</string>
<string name="briar_version">Briar 版本:%s</string>
<string name="tor_version">Tor 版本:%s</string>
<string name="links">链接</string>
<string name="briar_website">\u2022 <a href="">网站</a></string>
<string name="briar_source_code">\u2022 <a href="">源代码</a></string>
<string name="briar_changelog">\u2022 <a href="">变更记录</a></string>
<!--Here translators can add their names or Transifex usernames(eg "Thanks to all the contributors at the Localization Lab, especially Tom, Matthew and Jerry")-->
<string name="translator_thanks">感谢所有 Localization Lab 的贡献者们</string>
<!--Conversation Settings-->
<string name="disappearing_messages_title">让消息自动消失</string>
<string name="disappearing_messages_explanation_long">打开此设置将使

View File

@@ -665,7 +665,6 @@
<string name="mailbox_status_unlink_dialog_warning">If you unlink your Mailbox, you won\'t be able to receive messages while Briar is offline.</string>
<string name="mailbox_status_unlink_no_wipe_title">Your Mailbox has been unlinked</string>
<string name="mailbox_status_unlink_no_wipe_message">Next time you have access to your Mailbox device, please open the Mailbox app and tap the \"Unlink\" button to complete the process.\n\nIf you no longer have access to your Mailbox device, don\'t worry. Your data is encrypted so it will remain secure even if you don\'t complete the process.</string>
<string name="mailbox_status_unlink_success">Your Mailbox has been unlinked</string>
<string name="mailbox_error_notification_channel_title">Briar Mailbox problem</string>
<string name="mailbox_error_notification_title">Briar Mailbox is unavailable</string>
@@ -700,7 +699,6 @@
<string name="briar_website">\u2022 <a href="">Website</a></string>
<string name="briar_source_code">\u2022 <a href="">Source code</a></string>
<string name="briar_changelog">\u2022 <a href="">Changelog</a></string>
<string name="briar_privacy_policy">\u2022 <a href="">Privacy Policy</a></string>
<!-- Here translators can add their names or Transifex usernames(eg "Thanks to all the contributors at the Localization Lab, especially Tom, Matthew and Jerry") -->
<string name="translator_thanks">Thanks to all the contributors at the Localization Lab</string>
@@ -738,7 +736,6 @@
<string name="describe_crash">Describe what happened (optional)</string>
<string name="enter_feedback">Enter your feedback</string>
<string name="optional_contact_email">Your email address (optional)</string>
<string name="privacy_policy">By sending us data you agree to our <a href="">privacy policy</a></string>
<string name="include_debug_report_crash">Include anonymous data about the crash</string>
<string name="include_debug_report_feedback">Include anonymous data about this device</string>
<string name="dev_report_user_info">User information</string>

View File

@@ -5,7 +5,6 @@ targetCompatibility = 1.8
apply plugin: 'ru.vyarus.animalsniffer'
apply plugin: 'witness'
apply from: 'witness.gradle'
apply plugin: 'checkstyle'
dependencies {
implementation project(path: ':bramble-api', configuration: 'default')

View File

@@ -7,7 +7,6 @@ apply plugin: 'idea'
apply plugin: 'witness'
apply from: 'witness.gradle'
apply from: '../dagger.gradle'
apply plugin: 'checkstyle'
dependencies {
implementation project(path: ':briar-api', configuration: 'default')

View File

@@ -6,6 +6,7 @@ import org.briarproject.briar.avatar.AvatarModule;
import org.briarproject.briar.blog.BlogModule;
import org.briarproject.briar.client.BriarClientModule;
import org.briarproject.briar.conversation.ConversationModule;
import org.briarproject.briar.feed.DnsModule;
import org.briarproject.briar.feed.FeedModule;
import org.briarproject.briar.forum.ForumModule;
import org.briarproject.briar.identity.IdentityModule;
@@ -25,6 +26,7 @@ import dagger.Module;
BlogModule.class,
BriarClientModule.class,
ConversationModule.class,
DnsModule.class,
FeedModule.class,
ForumModule.class,
GroupInvitationModule.class,

View File

@@ -1,4 +1,4 @@
package org.briarproject.bramble.io;
package org.briarproject.briar.feed;
import dagger.Module;
import dagger.Provides;

View File

@@ -1,6 +1,4 @@
package org.briarproject.bramble.io;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
package org.briarproject.briar.feed;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -11,7 +9,6 @@ import javax.inject.Inject;
import okhttp3.Dns;
@NotNullByDefault
class NoDns implements Dns {
private static final byte[] UNSPECIFIED_ADDRESS = new byte[4];

View File

@@ -5,7 +5,6 @@ import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.bramble.test.TestDnsModule;
import org.briarproject.bramble.test.TestSocksModule;
import org.briarproject.briar.api.blog.BlogManager;
import org.briarproject.briar.api.feed.FeedManager;
@@ -13,6 +12,7 @@ import org.briarproject.briar.avatar.AvatarModule;
import org.briarproject.briar.blog.BlogModule;
import org.briarproject.briar.client.BriarClientModule;
import org.briarproject.briar.identity.IdentityModule;
import org.briarproject.briar.test.TestDnsModule;
import javax.inject.Singleton;
@@ -28,7 +28,7 @@ import dagger.Component;
FeedModule.class,
IdentityModule.class,
TestDnsModule.class,
TestSocksModule.class
TestSocksModule.class,
})
interface FeedManagerIntegrationTestComponent
extends BrambleCoreIntegrationTestEagerSingletons {

View File

@@ -2,8 +2,6 @@ package org.briarproject.briar.introduction;
import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.bramble.test.TestDnsModule;
import org.briarproject.bramble.test.TestSocksModule;
import org.briarproject.briar.attachment.AttachmentModule;
import org.briarproject.briar.autodelete.AutoDeleteModule;
import org.briarproject.briar.avatar.AvatarModule;
@@ -38,9 +36,7 @@ import dagger.Component;
IntroductionModule.class,
MessagingModule.class,
PrivateGroupModule.class,
SharingModule.class,
TestDnsModule.class,
TestSocksModule.class
SharingModule.class
})
interface IntroductionIntegrationTestComponent
extends BriarIntegrationTestComponent {

View File

@@ -3,8 +3,6 @@ package org.briarproject.briar.messaging;
import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons;
import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.bramble.test.TestDnsModule;
import org.briarproject.bramble.test.TestSocksModule;
import org.briarproject.briar.autodelete.AutoDeleteModule;
import org.briarproject.briar.avatar.AvatarModule;
import org.briarproject.briar.client.BriarClientModule;
@@ -26,9 +24,7 @@ import dagger.Component;
ConversationModule.class,
ForumModule.class,
IdentityModule.class,
MessagingModule.class,
TestDnsModule.class,
TestSocksModule.class
MessagingModule.class
})
interface MessageSizeIntegrationTestComponent
extends BrambleCoreIntegrationTestEagerSingletons {

View File

@@ -8,8 +8,6 @@ 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.test.BrambleCoreIntegrationTestModule;
import org.briarproject.bramble.test.TestDnsModule;
import org.briarproject.bramble.test.TestSocksModule;
import org.briarproject.briar.api.messaging.MessagingManager;
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
import org.briarproject.briar.autodelete.AutoDeleteModule;
@@ -27,9 +25,7 @@ import dagger.Component;
BrambleCoreModule.class,
BriarClientModule.class,
ConversationModule.class,
MessagingModule.class,
TestDnsModule.class,
TestSocksModule.class
MessagingModule.class
})
interface SimplexMessagingIntegrationTestComponent
extends BrambleCoreIntegrationTestEagerSingletons {

View File

@@ -10,8 +10,6 @@ import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.bramble.test.BrambleIntegrationTestComponent;
import org.briarproject.bramble.test.TestDnsModule;
import org.briarproject.bramble.test.TestSocksModule;
import org.briarproject.bramble.test.TimeTravel;
import org.briarproject.briar.api.attachment.AttachmentReader;
import org.briarproject.briar.api.autodelete.AutoDeleteManager;
@@ -63,9 +61,7 @@ import dagger.Component;
IntroductionModule.class,
MessagingModule.class,
PrivateGroupModule.class,
SharingModule.class,
TestDnsModule.class,
TestSocksModule.class
SharingModule.class
})
public interface BriarIntegrationTestComponent
extends BrambleIntegrationTestComponent {

View File

@@ -1,4 +1,4 @@
package org.briarproject.bramble.test;
package org.briarproject.briar.test;
import dagger.Module;
import dagger.Provides;

View File

@@ -3,7 +3,6 @@ package org.briarproject.briar.headless
import dagger.Component
import org.briarproject.bramble.BrambleCoreEagerSingletons
import org.briarproject.bramble.BrambleCoreModule
import org.briarproject.bramble.BrambleJavaModule
import org.briarproject.briar.BriarCoreEagerSingletons
import org.briarproject.briar.BriarCoreModule
import java.security.SecureRandom
@@ -12,7 +11,6 @@ import javax.inject.Singleton
@Component(
modules = [
BrambleCoreModule::class,
BrambleJavaModule::class,
BriarCoreModule::class,
HeadlessModule::class
]

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