diff --git a/briar-api/src/org/briarproject/api/db/DatabaseComponent.java b/briar-api/src/org/briarproject/api/db/DatabaseComponent.java
index 06800e1c4c57e90d24f38d47edc8af33e3c0b172..435d1025b159e561838478506c42fe82240a5a29 100644
--- a/briar-api/src/org/briarproject/api/db/DatabaseComponent.java
+++ b/briar-api/src/org/briarproject/api/db/DatabaseComponent.java
@@ -193,9 +193,6 @@ public interface DatabaseComponent {
 	/** Returns the maximum latencies in milliseconds of all transports. */
 	Map<TransportId, Integer> getTransportLatencies() throws DbException;
 
-	/** Returns the IDs of all contacts to which the given group is visible. */
-	Collection<ContactId> getVisibility(GroupId g) throws DbException;
-
 	/**
 	 * Increments the outgoing stream counter for the given contact and
 	 * transport in the given rotation period .
@@ -271,13 +268,6 @@ public interface DatabaseComponent {
 	void setReorderingWindow(ContactId c, TransportId t, long rotationPeriod,
 			long base, byte[] bitmap) throws DbException;
 
-	/**
-	 * Makes a group visible to the given set of contacts and invisible to any
-	 * other contacts.
-	 */
-	void setVisibility(GroupId g, Collection<ContactId> visible)
-			throws DbException;
-
 	/** Makes a group visible or invisible to a contact. */
 	void setVisibleToContact(ContactId c, GroupId g, boolean visible)
 			throws DbException;
diff --git a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java b/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java
index b62f180902efa827fcdbb6e31cfb138a809c9c4a..9e46dabb99a9cdcf59f8c76b95c6a8aed9695523 100644
--- a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java
+++ b/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java
@@ -638,20 +638,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 		}
 	}
 
-	public Collection<ContactId> getVisibility(GroupId g) throws DbException {
-		T txn = db.startTransaction();
-		try {
-			if (!db.containsGroup(txn, g))
-				throw new NoSuchGroupException();
-			Collection<ContactId> visible = db.getVisibility(txn, g);
-			db.commitTransaction(txn);
-			return visible;
-		} catch (DbException e) {
-			db.abortTransaction(txn);
-			throw e;
-		}
-	}
-
 	public void incrementStreamCounter(ContactId c, TransportId t,
 			long rotationPeriod) throws DbException {
 		T txn = db.startTransaction();
@@ -956,38 +942,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
 		}
 	}
 
-	public void setVisibility(GroupId g, Collection<ContactId> visible)
-			throws DbException {
-		Collection<ContactId> affected = new ArrayList<ContactId>();
-		T txn = db.startTransaction();
-		try {
-			if (!db.containsGroup(txn, g))
-				throw new NoSuchGroupException();
-			// Use HashSets for O(1) lookups, O(n) overall running time
-			Collection<ContactId> now = new HashSet<ContactId>(visible);
-			Collection<ContactId> before = db.getVisibility(txn, g);
-			before = new HashSet<ContactId>(before);
-			// Set the group's visibility for each current contact
-			for (ContactId c : db.getContactIds(txn)) {
-				boolean wasBefore = before.contains(c);
-				boolean isNow = now.contains(c);
-				if (!wasBefore && isNow) {
-					db.addVisibility(txn, c, g);
-					affected.add(c);
-				} else if (wasBefore && !isNow) {
-					db.removeVisibility(txn, c, g);
-					affected.add(c);
-				}
-			}
-			db.commitTransaction(txn);
-		} catch (DbException e) {
-			db.abortTransaction(txn);
-			throw e;
-		}
-		if (!affected.isEmpty())
-			eventBus.broadcast(new GroupVisibilityUpdatedEvent(affected));
-	}
-
 	public void setVisibleToContact(ContactId c, GroupId g, boolean visible)
 			throws DbException {
 		boolean wasVisible;
diff --git a/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java b/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java
index abfb7f6c90f8108bce42242ece447e2db26658d9..72efd00ac056eed7fbb1a24fae6816aa962adadd 100644
--- a/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java
+++ b/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java
@@ -113,7 +113,7 @@ class ForumSharingManagerImpl implements ForumSharingManager, AddContactHook,
 			Group g = getContactGroup(c);
 			// Store the group and share it with the contact
 			db.addGroup(g);
-			db.setVisibility(g.getId(), Collections.singletonList(c.getId()));
+			db.setVisibleToContact(c.getId(), g.getId(), true);
 			// Attach the contact ID to the group
 			BdfDictionary d = new BdfDictionary();
 			d.put("contactId", c.getId().getInt());
diff --git a/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java b/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java
index a5514fc04ae77bcb99e5369edcb8393cb707f0c5..5185cac6e8ae01e2250fd777257e04363e87a5f5 100644
--- a/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java
+++ b/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java
@@ -32,7 +32,6 @@ import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Map;
 import java.util.logging.Logger;
 
@@ -77,7 +76,7 @@ class MessagingManagerImpl implements MessagingManager, AddContactHook,
 			Group g = getContactGroup(c);
 			// Store the group and share it with the contact
 			db.addGroup(g);
-			db.setVisibility(g.getId(), Collections.singletonList(c.getId()));
+			db.setVisibleToContact(c.getId(), g.getId(), true);
 			// Attach the contact ID to the group
 			BdfDictionary d = new BdfDictionary();
 			d.put("contactId", c.getId().getInt());
diff --git a/briar-core/src/org/briarproject/properties/TransportPropertyManagerImpl.java b/briar-core/src/org/briarproject/properties/TransportPropertyManagerImpl.java
index e972093d7a03d2abb21edfe0c34140830526f900..a7babd5cdad32f7439e69f081d183e6b388dcf13 100644
--- a/briar-core/src/org/briarproject/properties/TransportPropertyManagerImpl.java
+++ b/briar-core/src/org/briarproject/properties/TransportPropertyManagerImpl.java
@@ -102,7 +102,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
 			Group g = getContactGroup(c);
 			// Store the group and share it with the contact
 			db.addGroup(g);
-			db.setVisibility(g.getId(), Collections.singletonList(c.getId()));
+			db.setVisibleToContact(c.getId(), g.getId(), true);
 			// Copy the latest local properties into the group
 			DeviceId dev = db.getDeviceId();
 			Map<TransportId, TransportProperties> local = getLocalProperties();
diff --git a/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java b/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java
index 178dee5b6a9a6730fe16dc3fe3ba00ac52c770f8..0743df9495bca6e22c29329ac6454fa863ac2dc1 100644
--- a/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java
+++ b/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java
@@ -455,11 +455,11 @@ public class DatabaseComponentImplTest extends BriarTestCase {
 		final EventBus eventBus = context.mock(EventBus.class);
 		context.checking(new Expectations() {{
 			// Check whether the group is in the DB (which it's not)
-			exactly(9).of(database).startTransaction();
+			exactly(7).of(database).startTransaction();
 			will(returnValue(txn));
-			exactly(9).of(database).containsGroup(txn, groupId);
+			exactly(7).of(database).containsGroup(txn, groupId);
 			will(returnValue(false));
-			exactly(9).of(database).abortTransaction(txn);
+			exactly(7).of(database).abortTransaction(txn);
 			// This is needed for getMessageStatus(), isVisibleToContact(), and
 			// setVisibleToContact() to proceed
 			exactly(3).of(database).containsContact(txn, contactId);
@@ -489,13 +489,6 @@ public class DatabaseComponentImplTest extends BriarTestCase {
 			// Expected
 		}
 
-		try {
-			db.getVisibility(groupId);
-			fail();
-		} catch (NoSuchGroupException expected) {
-			// Expected
-		}
-
 		try {
 			db.isVisibleToContact(contactId, groupId);
 			fail();
@@ -517,13 +510,6 @@ public class DatabaseComponentImplTest extends BriarTestCase {
 			// Expected
 		}
 
-		try {
-			db.setVisibility(groupId, Collections.<ContactId>emptyList());
-			fail();
-		} catch (NoSuchGroupException expected) {
-			// Expected
-		}
-
 		try {
 			db.setVisibleToContact(contactId, groupId, true);
 			fail();
@@ -1048,8 +1034,6 @@ public class DatabaseComponentImplTest extends BriarTestCase {
 
 	@Test
 	public void testChangingVisibilityCallsListeners() throws Exception {
-		final ContactId contactId1 = new ContactId(123);
-		final Collection<ContactId> both = Arrays.asList(contactId, contactId1);
 		Mockery context = new Mockery();
 		@SuppressWarnings("unchecked")
 		final Database<Object> database = context.mock(Database.class);
@@ -1058,13 +1042,13 @@ public class DatabaseComponentImplTest extends BriarTestCase {
 		context.checking(new Expectations() {{
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
+			oneOf(database).containsContact(txn, contactId);
+			will(returnValue(true));
 			oneOf(database).containsGroup(txn, groupId);
 			will(returnValue(true));
-			oneOf(database).getVisibility(txn, groupId);
-			will(returnValue(both));
-			oneOf(database).getContactIds(txn);
-			will(returnValue(both));
-			oneOf(database).removeVisibility(txn, contactId1, groupId);
+			oneOf(database).containsVisibleGroup(txn, contactId, groupId);
+			will(returnValue(false)); // Not yet visible
+			oneOf(database).addVisibility(txn, contactId, groupId);
 			oneOf(database).commitTransaction(txn);
 			oneOf(eventBus).broadcast(with(any(
 					GroupVisibilityUpdatedEvent.class)));
@@ -1072,7 +1056,7 @@ public class DatabaseComponentImplTest extends BriarTestCase {
 		DatabaseComponent db = createDatabaseComponent(database, eventBus,
 				shutdown);
 
-		db.setVisibility(groupId, Collections.singletonList(contactId));
+		db.setVisibleToContact(contactId, groupId, true);
 
 		context.assertIsSatisfied();
 	}
@@ -1080,8 +1064,6 @@ public class DatabaseComponentImplTest extends BriarTestCase {
 	@Test
 	public void testNotChangingVisibilityDoesNotCallListeners()
 			throws Exception {
-		final ContactId contactId1 = new ContactId(123);
-		final Collection<ContactId> both = Arrays.asList(contactId, contactId1);
 		Mockery context = new Mockery();
 		@SuppressWarnings("unchecked")
 		final Database<Object> database = context.mock(Database.class);
@@ -1090,18 +1072,18 @@ public class DatabaseComponentImplTest extends BriarTestCase {
 		context.checking(new Expectations() {{
 			oneOf(database).startTransaction();
 			will(returnValue(txn));
+			oneOf(database).containsContact(txn, contactId);
+			will(returnValue(true));
 			oneOf(database).containsGroup(txn, groupId);
 			will(returnValue(true));
-			oneOf(database).getVisibility(txn, groupId);
-			will(returnValue(both));
-			oneOf(database).getContactIds(txn);
-			will(returnValue(both));
+			oneOf(database).containsVisibleGroup(txn, contactId, groupId);
+			will(returnValue(true)); // Already visible
 			oneOf(database).commitTransaction(txn);
 		}});
 		DatabaseComponent db = createDatabaseComponent(database, eventBus,
 				shutdown);
 
-		db.setVisibility(groupId, both);
+		db.setVisibleToContact(contactId, groupId, true);
 
 		context.assertIsSatisfied();
 	}