From 6fcbb76665397dae6d6395f5155c955e4e052863 Mon Sep 17 00:00:00 2001 From: Timur Masar Date: Fri, 2 Oct 2015 07:41:43 +0200 Subject: Fixes the contacts 'call button' disappearing on multiresource contacts This changes the behaviour from "last connected resource" or "highest priority resource" to "most capable resource" regarding the display of buttons next to this contact. We now check every resource the contact has connected and we will consider the one with the most capabilities. This elimates the very frustrating scenario in which the call capabilites are disabled on a contact who connected additionally a non-jingle client. Note that there exists separate issue in which the contact logs off from only one resource, but gets displayed as completely offline. In that case the buttons are still displayed wrong, if the contact connects a non-jingle client on afterwards. --- .../OperationSetContactCapabilitiesJabberImpl.java | 74 +++++++++++++++++++--- 1 file changed, 65 insertions(+), 9 deletions(-) (limited to 'src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java') diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java index 0a6edfe..a1767dd 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java @@ -276,6 +276,41 @@ public class OperationSetContactCapabilitiesJabberImpl } /** + * Gets the largest set of OperationSets supported from a + * list of full JIDs. The returned OperationSets are considered + * by the associated protocol provider to capabilities possessed by the + * specified contact. + * + * @param fullJids a list of full JIDs in which to find the resource with + * the most capabilities. + * @return the Map listing the most OperationSets + * considered by the associated protocol provider to be supported by the + * specified contact (i.e. to be possessed as capabilities). + * Each supported OperationSet capability is represented by a + * Map.Entry with key equal to the OperationSet class + * name and value equal to the respective OperationSet instance + */ + protected Map getLargestSupportedOperationSet( + ArrayList fullJids) + { + Map supportedOperationSets = + new HashMap(); + if (fullJids!=null){ + for (String fullJid : fullJids) + { + Map newSupportedOperationSets= + getSupportedOperationSets(fullJid, true); + if (newSupportedOperationSets.size()> + supportedOperationSets.size()) + { + supportedOperationSets = newSupportedOperationSets; + } + } + } + return supportedOperationSets; + } + + /** * Gets the OperationSet corresponding to the specified * Class and supported by the specified Contact. If the * returned value is non-null, it indicates that the @@ -387,17 +422,19 @@ public class OperationSetContactCapabilitiesJabberImpl * record for a specific user about the caps node the user has. * * @param user the user (full JID) + * @param fullJids a list of all resources of the user (full JIDs) * @param node the entity caps node#ver * @param online indicates if the user is currently online * @see UserCapsNodeListener#userCapsNodeAdded(String, String, boolean) */ - public void userCapsNodeAdded(String user, String node, boolean online) + public void userCapsNodeAdded(String user, ArrayList fullJids, + String node, boolean online) { /* * It doesn't matter to us whether a caps node has been added or removed * for the specified user because we report all changes. */ - userCapsNodeRemoved(user, node, online); + userCapsNodeChanged(user, fullJids, node, online); } /** @@ -405,19 +442,39 @@ public class OperationSetContactCapabilitiesJabberImpl * record for a specific user about the caps node the user has. * * @param user the user (full JID) + * @param fullJids a list of all resources of the user (full JIDs) + * @param node the entity caps node#ver + * @param online indicates if the user is currently online + * @see UserCapsNodeListener#userCapsNodeAdded(String, String, boolean) + */ + public void userCapsNodeRemoved(String user, ArrayList fullJids, + String node, boolean online) + { + /* + * It doesn't matter to us whether a caps node has been added or removed + * for the specified user because we report all changes. + */ + userCapsNodeChanged(user, fullJids, node, online); + } + + /** + * Notifies this listener that an EntityCapsManager has changed a + * record for a specific user about the caps node the user has. + * + * @param user the user (full JID) + * @param fullJids a list of all resources of the user (full JIDs) * @param node the entity caps node#ver * @param online indicates if the given user is online - * @see UserCapsNodeListener#userCapsNodeRemoved(String, String, boolean) */ - public void userCapsNodeRemoved(String user, String node, boolean online) + public void userCapsNodeChanged(String user, ArrayList fullJids, String node, boolean online) { OperationSetPresence opsetPresence = parentProvider.getOperationSet(OperationSetPresence.class); if (opsetPresence != null) { - String jid = StringUtils.parseBareAddress(user); - Contact contact = opsetPresence.findContactByID(jid); + String bareJid = StringUtils.parseBareAddress(user); + Contact contact = opsetPresence.findContactByID(bareJid); // If the contact isn't null and is online we try to discover the // new set of operation sets and to notify interested parties. @@ -432,8 +489,7 @@ public class OperationSetContactCapabilitiesJabberImpl fireContactCapabilitiesEvent( contact, ContactCapabilitiesEvent.SUPPORTED_OPERATION_SETS_CHANGED, - getSupportedOperationSets(user, - online)); + getLargestSupportedOperationSet(fullJids)); } else { @@ -443,7 +499,7 @@ public class OperationSetContactCapabilitiesJabberImpl fireContactCapabilitiesEvent( contact, ContactCapabilitiesEvent.SUPPORTED_OPERATION_SETS_CHANGED, - getSupportedOperationSets(contact)); + getLargestSupportedOperationSet(fullJids)); } } } -- cgit v1.1 From 45d8ee64c40fcb4d695c846e3fc4ab61fc9fbdad Mon Sep 17 00:00:00 2001 From: Timur Masar Date: Sat, 31 Oct 2015 04:06:24 +0100 Subject: Option for new behaviour of detecting a contact's capabilities This reintroduces some old code in order to give the user the option to switch between those two behaviours. It also prevents the removal of all caps nodes (and thusly breaking the new detection) when a rogue offline presence event comes in. This is such an event in which a contact is falsely assumed as offline, if the preferred resource of two or more same prioritised resources goes offline. We are checking this by looking whether it is a "resourceChanged"-event. This should probably be changed again, after those offline presence updates have been fixed. --- .../OperationSetContactCapabilitiesJabberImpl.java | 160 ++++++++++++++------- 1 file changed, 112 insertions(+), 48 deletions(-) (limited to 'src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java') diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java index a1767dd..e74ace1 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java @@ -26,7 +26,7 @@ import net.java.sip.communicator.service.protocol.event.*; import net.java.sip.communicator.util.*; import org.jivesoftware.smack.packet.*; -import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smack.util.*; /** * Represents an OperationSet to query the OperationSets @@ -52,6 +52,19 @@ public class OperationSetContactCapabilitiesJabberImpl = Logger.getLogger(OperationSetContactCapabilitiesJabberImpl.class); /** + * The name of the property used to control whether to use + * all resources to show capabilities + */ + public static final String PROP_XMPP_USE_ALL_RESOURCES_FOR_CAPABILITIES = + "net.java.sip.communicator.XMPP_USE_ALL_RESOURCES_FOR_CAPABILITIES"; + + /** + * The default value for the capabilities setting + */ + public static final boolean USE_ALL_RESOURCES_FOR_CAPABILITIES_DEFAULT = + true; + + /** * The list of OperationSet capabilities presumed to be supported * by a Contact when it is offline. */ @@ -295,13 +308,14 @@ public class OperationSetContactCapabilitiesJabberImpl { Map supportedOperationSets = new HashMap(); - if (fullJids!=null){ + if (fullJids!=null) + { for (String fullJid : fullJids) { Map newSupportedOperationSets= getSupportedOperationSets(fullJid, true); if (newSupportedOperationSets.size()> - supportedOperationSets.size()) + supportedOperationSets.size()) { supportedOperationSets = newSupportedOperationSets; } @@ -466,40 +480,61 @@ public class OperationSetContactCapabilitiesJabberImpl * @param node the entity caps node#ver * @param online indicates if the given user is online */ - public void userCapsNodeChanged(String user, ArrayList fullJids, String node, boolean online) + public void userCapsNodeChanged(String user, ArrayList fullJids, + String node, boolean online) { OperationSetPresence opsetPresence - = parentProvider.getOperationSet(OperationSetPresence.class); - - if (opsetPresence != null) - { - String bareJid = StringUtils.parseBareAddress(user); - Contact contact = opsetPresence.findContactByID(bareJid); - - // If the contact isn't null and is online we try to discover the - // new set of operation sets and to notify interested parties. - // Otherwise we ignore the event. - if (contact != null) + = parentProvider.getOperationSet(OperationSetPresence.class); + if (opsetPresence != null) { + if(JabberActivator.getConfigurationService() + .getBoolean( + PROP_XMPP_USE_ALL_RESOURCES_FOR_CAPABILITIES, + USE_ALL_RESOURCES_FOR_CAPABILITIES_DEFAULT)) { - if(online) + String bareJid = StringUtils.parseBareAddress(user); + Contact contact = opsetPresence.findContactByID(bareJid); + if (contact != null) { - // when going online we have received a presence - // and make sure we discover this particular jid - // for getSupportedOperationSets fireContactCapabilitiesEvent( contact, - ContactCapabilitiesEvent.SUPPORTED_OPERATION_SETS_CHANGED, + ContactCapabilitiesEvent. + SUPPORTED_OPERATION_SETS_CHANGED, getLargestSupportedOperationSet(fullJids)); } - else + } + else + { + String jid = StringUtils.parseBareAddress(user); + Contact contact = opsetPresence.findContactByID(jid); + + // If the contact isn't null and is online we try to discover + // the new set of operation sets and to notify interested + // parties. Otherwise we ignore the event. + if (contact != null) { - // when offline, we use the contact, and selecting - // the most connected jid - // for getSupportedOperationSets - fireContactCapabilitiesEvent( - contact, - ContactCapabilitiesEvent.SUPPORTED_OPERATION_SETS_CHANGED, - getLargestSupportedOperationSet(fullJids)); + if(online) + { + // when going online we have received a presence + // and make sure we discover this particular jid + // for getSupportedOperationSets + fireContactCapabilitiesEvent( + contact, + ContactCapabilitiesEvent. + SUPPORTED_OPERATION_SETS_CHANGED, + getSupportedOperationSets(user, + online)); + } + else + { + // when offline, we use the contact, and selecting + // the most connected jid + // for getSupportedOperationSets + fireContactCapabilitiesEvent( + contact, + ContactCapabilitiesEvent. + SUPPORTED_OPERATION_SETS_CHANGED, + getSupportedOperationSets(contact)); + } } } } @@ -516,7 +551,8 @@ public class OperationSetContactCapabilitiesJabberImpl { // If the user goes offline we ensure to remove the caps node. if (capsManager != null - && evt.getNewStatus().getStatus() < PresenceStatus.ONLINE_THRESHOLD) + && evt.getNewStatus().getStatus() < PresenceStatus.ONLINE_THRESHOLD + && !evt.isResourceChanged()) { capsManager.removeContactCapsNode(evt.getSourceContact()); } @@ -525,31 +561,59 @@ public class OperationSetContactCapabilitiesJabberImpl /** * Fires event that contact capabilities has changed. * @param user the user to search for its contact. + * @param fullJids a list of all resources of the user (full JIDs) */ - public void fireContactCapabilitiesChanged(String user) + public void fireContactCapabilitiesChanged(String user, + ArrayList fullJids) { - OperationSetPresence opsetPresence + if(!JabberActivator.getConfigurationService() + .getBoolean( + PROP_XMPP_USE_ALL_RESOURCES_FOR_CAPABILITIES, + USE_ALL_RESOURCES_FOR_CAPABILITIES_DEFAULT) + ||fullJids.isEmpty()) + { + OperationSetPresence opsetPresence = parentProvider.getOperationSet(OperationSetPresence.class); - if (opsetPresence != null) + if (opsetPresence != null) + { + String userID = StringUtils.parseBareAddress(user); + Contact contact = opsetPresence.findContactByID(userID); + + // this called by received discovery info for particular jid + // so we use its online and opsets for this particular jid + boolean online = false; + Presence presence = parentProvider.getConnection().getRoster() + .getPresence(user); + if(presence != null) + online = presence.isAvailable(); + + if(contact != null) + { + fireContactCapabilitiesEvent( + contact, + ContactCapabilitiesEvent. + SUPPORTED_OPERATION_SETS_CHANGED, + getSupportedOperationSets(user, online)); + } + } + } + else { - String userID = StringUtils.parseBareAddress(user); - Contact contact = opsetPresence.findContactByID(userID); - - // this called by received discovery info for particular jid - // so we use its online and opsets for this particular jid - boolean online = false; - Presence presence = parentProvider.getConnection().getRoster() - .getPresence(user); - if(presence != null) - online = presence.isAvailable(); - - if(contact != null) + OperationSetPresence opsetPresence + = parentProvider.getOperationSet(OperationSetPresence.class); + if (opsetPresence != null) { - fireContactCapabilitiesEvent( - contact, - ContactCapabilitiesEvent.SUPPORTED_OPERATION_SETS_CHANGED, - getSupportedOperationSets(user, online)); + String bareJid = StringUtils.parseBareAddress(user); + Contact contact = opsetPresence.findContactByID(bareJid); + if(contact != null) + { + fireContactCapabilitiesEvent( + contact, + ContactCapabilitiesEvent. + SUPPORTED_OPERATION_SETS_CHANGED, + getLargestSupportedOperationSet(fullJids)); + } } } } -- cgit v1.1 From 79efc958b095fcf62cad8ac0306db220ec99ac8b Mon Sep 17 00:00:00 2001 From: Timur Masar Date: Tue, 10 Nov 2015 02:55:41 +0100 Subject: Fixes offline messaging to contact which just went offline We should still use the old implementation for checking offline contacts capabilities. This will give us the 'offline capabilities' e.g. messaging offline contacts. --- .../protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java') diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java index e74ace1..59cc17c 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java @@ -489,7 +489,8 @@ public class OperationSetContactCapabilitiesJabberImpl if(JabberActivator.getConfigurationService() .getBoolean( PROP_XMPP_USE_ALL_RESOURCES_FOR_CAPABILITIES, - USE_ALL_RESOURCES_FOR_CAPABILITIES_DEFAULT)) + USE_ALL_RESOURCES_FOR_CAPABILITIES_DEFAULT) + && !fullJids.isEmpty()) { String bareJid = StringUtils.parseBareAddress(user); Contact contact = opsetPresence.findContactByID(bareJid); @@ -570,7 +571,7 @@ public class OperationSetContactCapabilitiesJabberImpl .getBoolean( PROP_XMPP_USE_ALL_RESOURCES_FOR_CAPABILITIES, USE_ALL_RESOURCES_FOR_CAPABILITIES_DEFAULT) - ||fullJids.isEmpty()) + || fullJids.isEmpty()) { OperationSetPresence opsetPresence = parentProvider.getOperationSet(OperationSetPresence.class); -- cgit v1.1