fetch device ids for muc members w/o known devices

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java  | 23 
src/main/java/eu/siacs/conversations/entities/MucOptions.java            | 10 
src/main/java/eu/siacs/conversations/parser/MessageParser.java           |  4 
src/main/java/eu/siacs/conversations/parser/PresenceParser.java          |  7 
src/main/java/eu/siacs/conversations/services/XmppConnectionService.java |  6 
5 files changed, 44 insertions(+), 6 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java 🔗

@@ -211,7 +211,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
 			putDevicesForJid(account.getJid().toBareJid().toPreppedString(), deviceIds, store);
 			for (Contact contact : account.getRoster().getContacts()) {
 				Jid bareJid = contact.getJid().toBareJid();
-				String address = bareJid.toString();
+				String address = bareJid.toPreppedString();
 				deviceIds = store.getSubDeviceSessions(address);
 				putDevicesForJid(address, deviceIds, store);
 			}
@@ -842,6 +842,27 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
 		}
 	}
 
+	public boolean hasEmptyDeviceList(Jid jid) {
+		return !hasAny(jid) && (!deviceIds.containsKey(jid) || deviceIds.get(jid).isEmpty());
+	}
+
+	public void fetchDeviceIds(final Jid jid) {
+		Log.d(Config.LOGTAG,"fetching device ids for "+jid);
+		IqPacket packet = mXmppConnectionService.getIqGenerator().retrieveDeviceIds(jid);
+		mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() {
+			@Override
+			public void onIqPacketReceived(Account account, IqPacket packet) {
+				if (packet.getType() == IqPacket.TYPE.RESULT) {
+					Element item = mXmppConnectionService.getIqParser().getItem(packet);
+					Set<Integer> deviceIds = mXmppConnectionService.getIqParser().deviceIds(item);
+					registerDevices(jid,deviceIds);
+				} else {
+					Log.d(Config.LOGTAG,packet.toString());
+				}
+			}
+		});
+	}
+
 	private void buildSessionFromPEP(final SignalProtocolAddress address) {
 		Log.i(Config.LOGTAG, AxolotlService.getLogprefix(account) + "Building new session for " + address.toString());
 		if (address.equals(getOwnAxolotlAddress())) {

src/main/java/eu/siacs/conversations/entities/MucOptions.java 🔗

@@ -450,13 +450,16 @@ public class MucOptions {
 		return user;
 	}
 
-	public void updateUser(User user) {
+	//returns true if real jid was new;
+	public boolean updateUser(User user) {
 		User old;
+		boolean realJidFound = false;
 		if (user.fullJid == null && user.realJid != null) {
 			old = findUserByRealJid(user.realJid);
+			realJidFound = old != null;
 			if (old != null) {
 				if (old.fullJid != null) {
-					return; //don't add. user already exists
+					return false; //don't add. user already exists
 				} else {
 					synchronized (users) {
 						users.remove(old);
@@ -465,6 +468,7 @@ public class MucOptions {
 			}
 		} else if (user.realJid != null) {
 			old = findUserByRealJid(user.realJid);
+			realJidFound = old != null;
 			synchronized (users) {
 				if (old != null && old.fullJid == null) {
 					users.remove(old);
@@ -481,8 +485,10 @@ public class MucOptions {
 					&& user.getAffiliation().outranks(Affiliation.OUTCAST)
 					&& !fullJidIsSelf){
 				this.users.add(user);
+				return !realJidFound && user.realJid != null;
 			}
 		}
+		return false;
 	}
 
 	public User findUserByFullJid(Jid jid) {

src/main/java/eu/siacs/conversations/parser/MessageParser.java 🔗

@@ -667,7 +667,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
 								+user.getRealJid()+" to "+user.getAffiliation()+" in "
 								+conversation.getJid().toBareJid());
 						if (!user.realJidMatchesAccount()) {
-							conversation.getMucOptions().updateUser(user);
+							boolean isNew =conversation.getMucOptions().updateUser(user);
 							mXmppConnectionService.getAvatarService().clear(conversation);
 							mXmppConnectionService.updateMucRosterUi();
 							mXmppConnectionService.updateConversationUi();
@@ -679,6 +679,8 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
 									conversation.setAcceptedCryptoTargets(cryptoTargets);
 									mXmppConnectionService.updateConversation(conversation);
 								}
+							} else if (isNew && user.getRealJid() != null && account.getAxolotlService().hasEmptyDeviceList(user.getRealJid())) {
+								account.getAxolotlService().fetchDeviceIds(user.getRealJid());
 							}
 						}
 					}

src/main/java/eu/siacs/conversations/parser/PresenceParser.java 🔗

@@ -9,6 +9,7 @@ import java.util.List;
 
 import eu.siacs.conversations.Config;
 import eu.siacs.conversations.crypto.PgpEngine;
+import eu.siacs.conversations.crypto.axolotl.AxolotlService;
 import eu.siacs.conversations.entities.Account;
 import eu.siacs.conversations.entities.Contact;
 import eu.siacs.conversations.entities.Conversation;
@@ -76,7 +77,11 @@ public class PresenceParser extends AbstractParser implements
 								mucOptions.onRenameListener = null;
 							}
 						}
-						mucOptions.updateUser(user);
+						boolean isNew = mucOptions.updateUser(user);
+						final AxolotlService axolotlService = conversation.getAccount().getAxolotlService();
+						if (isNew && user.getRealJid() != null && mucOptions.membersOnly() && mucOptions.nonanonymous() && axolotlService.hasEmptyDeviceList(user.getRealJid())) {
+							axolotlService.fetchDeviceIds(user.getRealJid());
+						}
 						if (codes.contains(MucOptions.STATUS_CODE_ROOM_CREATED) && mucOptions.autoPushConfiguration()) {
 							Log.d(Config.LOGTAG,mucOptions.getAccount().getJid().toBareJid()
 									+": room '"

src/main/java/eu/siacs/conversations/services/XmppConnectionService.java 🔗

@@ -2313,6 +2313,7 @@ public class XmppConnectionService extends Service {
 
 	private void fetchConferenceMembers(final Conversation conversation) {
 		final Account account = conversation.getAccount();
+		final AxolotlService axolotlService = account.getAxolotlService();
 		final String[] affiliations = {"member","admin","owner"};
 		OnIqPacketReceived callback = new OnIqPacketReceived() {
 
@@ -2328,7 +2329,10 @@ public class XmppConnectionService extends Service {
 						if ("item".equals(child.getName())) {
 							MucOptions.User user = AbstractParser.parseItem(conversation,child);
 							if (!user.realJidMatchesAccount()) {
-								conversation.getMucOptions().updateUser(user);
+								boolean isNew = conversation.getMucOptions().updateUser(user);
+								if (isNew && user.getRealJid() != null && axolotlService.hasEmptyDeviceList(user.getRealJid())) {
+									axolotlService.fetchDeviceIds(user.getRealJid());
+								}
 							}
 						}
 					}