diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/event/MailboxUpdateSentEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/event/MailboxUpdateSentEvent.java
new file mode 100644
index 000000000..4017780bd
--- /dev/null
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/mailbox/event/MailboxUpdateSentEvent.java
@@ -0,0 +1,39 @@
+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 javax.annotation.concurrent.Immutable;
+
+/**
+ * An event that is broadcast when a mailbox update is sent to a contact.
+ *
+ * Note that this event is not broadcast when a mailbox is paired or
+ * unpaired, although updates are sent to all contacts in those situations.
+ *
+ * @see MailboxPairedEvent
+ * @see MailboxUnpairedEvent
+ */
+@Immutable
+@NotNullByDefault
+public class MailboxUpdateSentEvent extends Event {
+
+ private final ContactId contactId;
+ private final MailboxUpdate mailboxUpdate;
+
+ public MailboxUpdateSentEvent(ContactId contactId,
+ MailboxUpdate mailboxUpdate) {
+ this.contactId = contactId;
+ this.mailboxUpdate = mailboxUpdate;
+ }
+
+ public ContactId getContactId() {
+ return contactId;
+ }
+
+ public MailboxUpdate getMailboxUpdate() {
+ return mailboxUpdate;
+ }
+}
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxUpdateManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxUpdateManagerImpl.java
index 17857551b..4a6556c52 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxUpdateManagerImpl.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/mailbox/MailboxUpdateManagerImpl.java
@@ -27,6 +27,7 @@ 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.MailboxUpdateSentEvent;
import org.briarproject.bramble.api.mailbox.event.RemoteMailboxUpdateEvent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Group;
@@ -114,6 +115,7 @@ class MailboxUpdateManagerImpl implements MailboxUpdateManager,
}
Group g = getContactGroup(c);
storeMessageReplaceLatest(txn, g.getId(), updated);
+ txn.attach(new MailboxUpdateSentEvent(c.getId(), updated));
}
} else {
db.addGroup(txn, localGroup);
@@ -146,14 +148,16 @@ 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
- createAndSendUpdateWithMailbox(txn, c, ownProps.getServerSupports(),
- ownProps.getOnion());
+ u = createAndSendUpdateWithMailbox(txn, c,
+ ownProps.getServerSupports(), ownProps.getOnion());
} else {
// Not paired, but we still want to get our clientSupports sent
- sendUpdateNoMailbox(txn, c);
+ u = sendUpdateNoMailbox(txn, c);
}
+ txn.attach(new MailboxUpdateSentEvent(c.getId(), u));
}
@Override
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxUpdateManagerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxUpdateManagerImplTest.java
index d149c0be8..f176dc89b 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxUpdateManagerImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/mailbox/MailboxUpdateManagerImplTest.java
@@ -19,6 +19,7 @@ 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.MailboxUpdateSentEvent;
import org.briarproject.bramble.api.mailbox.event.RemoteMailboxUpdateEvent;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId;
@@ -185,6 +186,9 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.onDatabaseOpened(txn);
+
+ MailboxUpdateSentEvent e = getEvent(txn, MailboxUpdateSentEvent.class);
+ assertNoMailboxPropertiesSent(e, someClientSupportsList);
}
@Test
@@ -238,11 +242,15 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.onDatabaseOpened(txn);
+
+ MailboxUpdateSentEvent e = getEvent(txn, MailboxUpdateSentEvent.class);
+ assertMailboxPropertiesSent(e, someClientSupportsList);
}
@Test
public void testUnchangedClientSupportsOnSecondStartup() throws Exception {
- Transaction txn = new Transaction(null, false);
+ Transaction txn1 = new Transaction(null, false);
+ Transaction txn2 = new Transaction(null, false);
Map emptyMessageMetadata =
new LinkedHashMap<>();
@@ -251,46 +259,49 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
someClientSupports));
context.checking(new Expectations() {{
- oneOf(db).containsGroup(txn, localGroup.getId());
+ oneOf(db).containsGroup(txn1, localGroup.getId());
will(returnValue(false));
- oneOf(db).addGroup(txn, localGroup);
- oneOf(db).getContacts(txn);
+ oneOf(db).addGroup(txn1, localGroup);
+ oneOf(db).getContacts(txn1);
will(returnValue(singletonList(contact)));
// addingContact()
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
- oneOf(db).addGroup(txn, contactGroup);
- oneOf(clientVersioningManager).getClientVisibility(txn,
+ oneOf(db).addGroup(txn1, contactGroup);
+ oneOf(clientVersioningManager).getClientVisibility(txn1,
contact.getId(), CLIENT_ID, MAJOR_VERSION);
will(returnValue(SHARED));
- oneOf(db).setGroupVisibility(txn, contact.getId(),
+ oneOf(db).setGroupVisibility(txn1, contact.getId(),
contactGroupId, SHARED);
- oneOf(clientHelper).setContactId(txn, contactGroupId,
+ oneOf(clientHelper).setContactId(txn1, contactGroupId,
contact.getId());
- oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn);
+ oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn1);
will(returnValue(null));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
- oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
+ oneOf(clientHelper).getMessageMetadataAsDictionary(txn1,
contactGroupId);
will(returnValue(emptyMessageMetadata));
- expectStoreMessage(txn, contactGroupId, 1, someClientSupports,
+ expectStoreMessage(txn1, contactGroupId, 1, someClientSupports,
emptyServerSupports, emptyPropsDict);
- oneOf(clientHelper).mergeGroupMetadata(txn, localGroup.getId(),
+ oneOf(clientHelper).mergeGroupMetadata(txn1, localGroup.getId(),
sentDict);
}});
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
- t.onDatabaseOpened(txn);
+ t.onDatabaseOpened(txn1);
+
+ MailboxUpdateSentEvent e = getEvent(txn1, MailboxUpdateSentEvent.class);
+ assertNoMailboxPropertiesSent(e, someClientSupportsList);
context.checking(new Expectations() {{
- oneOf(db).containsGroup(txn, localGroup.getId());
+ oneOf(db).containsGroup(txn2, localGroup.getId());
will(returnValue(true));
- oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
+ oneOf(clientHelper).getGroupMetadataAsDictionary(txn2,
localGroup.getId());
will(returnValue(sentDict));
oneOf(clientHelper).parseMailboxVersionList(someClientSupports);
@@ -298,13 +309,16 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
}});
t = createInstance(someClientSupportsList);
- t.onDatabaseOpened(txn);
+ t.onDatabaseOpened(txn2);
+
+ assertFalse(hasEvent(txn2, MailboxUpdateSentEvent.class));
}
@Test
public void testSendsUpdateWhenClientSupportsChangedOnSecondStartup()
throws Exception {
- Transaction txn = new Transaction(null, false);
+ Transaction txn1 = new Transaction(null, false);
+ Transaction txn2 = new Transaction(null, false);
Map emptyMessageMetadata =
new LinkedHashMap<>();
@@ -313,41 +327,45 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
someClientSupports));
context.checking(new Expectations() {{
- oneOf(db).containsGroup(txn, localGroup.getId());
+ oneOf(db).containsGroup(txn1, localGroup.getId());
will(returnValue(false));
- oneOf(db).addGroup(txn, localGroup);
- oneOf(db).getContacts(txn);
+ oneOf(db).addGroup(txn1, localGroup);
+ oneOf(db).getContacts(txn1);
will(returnValue(singletonList(contact)));
// addingContact()
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
- oneOf(db).addGroup(txn, contactGroup);
- oneOf(clientVersioningManager).getClientVisibility(txn,
+ oneOf(db).addGroup(txn1, contactGroup);
+ oneOf(clientVersioningManager).getClientVisibility(txn1,
contact.getId(), CLIENT_ID, MAJOR_VERSION);
will(returnValue(SHARED));
- oneOf(db).setGroupVisibility(txn, contact.getId(),
+ oneOf(db).setGroupVisibility(txn1, contact.getId(),
contactGroupId, SHARED);
- oneOf(clientHelper).setContactId(txn, contactGroupId,
+ oneOf(clientHelper).setContactId(txn1, contactGroupId,
contact.getId());
- oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn);
+ oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn1);
will(returnValue(null));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
- oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
+ oneOf(clientHelper).getMessageMetadataAsDictionary(txn1,
contactGroupId);
will(returnValue(emptyMessageMetadata));
- expectStoreMessage(txn, contactGroupId, 1, someClientSupports,
+ expectStoreMessage(txn1, contactGroupId, 1, someClientSupports,
emptyServerSupports, emptyPropsDict);
- oneOf(clientHelper).mergeGroupMetadata(txn, localGroup.getId(),
+ oneOf(clientHelper).mergeGroupMetadata(txn1, localGroup.getId(),
sentDict);
}});
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
- t.onDatabaseOpened(txn);
+ t.onDatabaseOpened(txn1);
+
+ MailboxUpdateSentEvent e1 =
+ getEvent(txn1, MailboxUpdateSentEvent.class);
+ assertNoMailboxPropertiesSent(e1, someClientSupportsList);
BdfDictionary metaDictionary = BdfDictionary.of(
new BdfEntry(MSG_KEY_VERSION, 1),
@@ -356,58 +374,62 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
Map messageMetadata = new LinkedHashMap<>();
MessageId messageId = new MessageId(getRandomId());
messageMetadata.put(messageId, metaDictionary);
- BdfList body = BdfList.of(1, someClientSupports, someServerSupports,
- propsDict);
+ BdfList oldBody = BdfList.of(1, someClientSupports, emptyServerSupports,
+ emptyPropsDict);
BdfDictionary newerSentDict = BdfDictionary.of(new BdfEntry(
GROUP_KEY_SENT_CLIENT_SUPPORTS,
newerClientSupports));
context.checking(new Expectations() {{
- oneOf(db).containsGroup(txn, localGroup.getId());
+ oneOf(db).containsGroup(txn2, localGroup.getId());
will(returnValue(true));
// Find out that we are now on newerClientSupportsList
- oneOf(clientHelper).getGroupMetadataAsDictionary(txn,
+ oneOf(clientHelper).getGroupMetadataAsDictionary(txn2,
localGroup.getId());
will(returnValue(sentDict));
oneOf(clientHelper).parseMailboxVersionList(someClientSupports);
will(returnValue(someClientSupportsList));
- oneOf(db).getContacts(txn);
+ oneOf(db).getContacts(txn2);
will(returnValue(singletonList(contact)));
- oneOf(db).getContact(txn, contact.getId());
+ oneOf(db).getContact(txn2, contact.getId());
will(returnValue(contact));
// getLocalUpdate()
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
- oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
+ oneOf(clientHelper).getMessageMetadataAsDictionary(txn2,
contactGroupId);
will(returnValue(messageMetadata));
- oneOf(clientHelper).getMessageAsList(txn, messageId);
- will(returnValue(body));
+ oneOf(clientHelper).getMessageAsList(txn2, messageId);
+ will(returnValue(oldBody));
oneOf(clientHelper).parseAndValidateMailboxUpdate(
- someClientSupports, someServerSupports, propsDict);
- will(returnValue(updateWithMailbox));
+ someClientSupports, emptyServerSupports, emptyPropsDict);
+ will(returnValue(updateNoMailbox));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact);
will(returnValue(contactGroup));
// storeMessageReplaceLatest()
- oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
+ oneOf(clientHelper).getMessageMetadataAsDictionary(txn2,
contactGroupId);
will(returnValue(messageMetadata));
- expectStoreMessage(txn, contactGroupId, 2,
- newerClientSupports, someServerSupports, propsDict);
- oneOf(db).removeMessage(txn, messageId);
+ expectStoreMessage(txn2, contactGroupId, 2,
+ newerClientSupports, emptyServerSupports, emptyPropsDict);
+ oneOf(db).removeMessage(txn2, messageId);
- oneOf(clientHelper).mergeGroupMetadata(txn, localGroup.getId(),
+ oneOf(clientHelper).mergeGroupMetadata(txn2, localGroup.getId(),
newerSentDict);
}});
t = createInstance(newerClientSupportsList);
- t.onDatabaseOpened(txn);
+ t.onDatabaseOpened(txn2);
+
+ MailboxUpdateSentEvent e2 =
+ getEvent(txn2, MailboxUpdateSentEvent.class);
+ assertNoMailboxPropertiesSent(e2, newerClientSupportsList);
}
@Test
@@ -443,6 +465,9 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.addingContact(txn, contact);
+
+ MailboxUpdateSentEvent e = getEvent(txn, MailboxUpdateSentEvent.class);
+ assertNoMailboxPropertiesSent(e, someClientSupportsList);
}
@Test
@@ -484,6 +509,9 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.addingContact(txn, contact);
+
+ MailboxUpdateSentEvent e = getEvent(txn, MailboxUpdateSentEvent.class);
+ assertMailboxPropertiesSent(e, someClientSupportsList);
}
@Test
@@ -693,6 +721,8 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
u.getClientSupports());
assertEquals(updateWithMailbox.getMailboxProperties(),
u.getMailboxProperties());
+
+ assertFalse(hasEvent(txn, MailboxUpdateSentEvent.class));
}
@Test
@@ -734,6 +764,8 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
assertEquals(singleton(contact.getId()), localUpdates.keySet());
MailboxUpdate u = localUpdates.get(contact.getId());
assertFalse(u.hasMailbox());
+
+ assertFalse(hasEvent(txn, MailboxUpdateSentEvent.class));
}
@Test
@@ -915,4 +947,22 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
false);
}});
}
+
+ private void assertNoMailboxPropertiesSent(MailboxUpdateSentEvent e,
+ List clientSupports) {
+ assertEquals(contact.getId(), e.getContactId());
+ MailboxUpdate u = e.getMailboxUpdate();
+ assertEquals(clientSupports, u.getClientSupports());
+ assertFalse(u.hasMailbox());
+ }
+
+ private void assertMailboxPropertiesSent(MailboxUpdateSentEvent e,
+ List 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());
+ }
}