diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 1a3b8a296a1894336dd69897ad74ef89d2fea43f..eca7e505814a47649cf260985e53304302b23110 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -1889,18 +1889,16 @@ public class XmppConnectionService extends Service { public void requestEasyOnboardingInvite( final Account account, final EasyOnboardingInvite.OnInviteRequested callback) { - final XmppConnection connection = account.getXmppConnection(); - final Jid jid = - connection == null - ? null - : connection.getJidForCommand(Namespace.EASY_ONBOARDING_INVITE); - if (jid == null) { + final var connection = account.getXmppConnection(); + final var discoManager = connection.getManager(DiscoManager.class); + final var address = discoManager.getAddressForCommand(Namespace.EASY_ONBOARDING_INVITE); + if (address == null) { callback.inviteRequestFailed( getString(R.string.server_does_not_support_easy_onboarding_invites)); return; } final Iq request = new Iq(Iq.Type.SET); - request.setTo(jid); + request.setTo(address); final Element command = request.addChild("command", Namespace.COMMANDS); command.setAttribute("node", Namespace.EASY_ONBOARDING_INVITE); command.setAttribute("action", "execute"); @@ -1922,7 +1920,7 @@ public class XmppConnectionService extends Service { if (uri != null) { final EasyOnboardingInvite invite = new EasyOnboardingInvite( - jid.getDomain().toString(), uri, landingUrl); + address.getDomain().toString(), uri, landingUrl); callback.inviteRequested(invite); return; } diff --git a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java index 7719a5fefdc1febc102820111f88e5e3b2016bcd..ea1ba280ff3da806617aa7af970e1f0335add1f9 100644 --- a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java @@ -523,8 +523,7 @@ public class ContactDetailsActivity extends OmemoActivity final String account = contact.getAccount().getJid().asBareJid().toString(); binding.detailsAccount.setOnClickListener(this::onDetailsAccountClicked); binding.detailsAccount.setText(getString(R.string.using_account, account)); - AvatarWorkerTask.loadAvatar( - contact, binding.detailsAvatar, R.dimen.publish_avatar_size); + AvatarWorkerTask.loadAvatar(contact, binding.detailsAvatar, R.dimen.publish_avatar_size); binding.detailsAvatar.setOnClickListener(this::onAvatarClicked); if (QuickConversationsService.isContactListIntegration(this)) { if (contact.getSystemAccount() == null) { diff --git a/src/main/java/eu/siacs/conversations/utils/EasyOnboardingInvite.java b/src/main/java/eu/siacs/conversations/utils/EasyOnboardingInvite.java index 37bce5e22830562b5d216132d20fb7f1b470f648..b097806d1d921488ee1312b23f69a3b9cd448dbb 100644 --- a/src/main/java/eu/siacs/conversations/utils/EasyOnboardingInvite.java +++ b/src/main/java/eu/siacs/conversations/utils/EasyOnboardingInvite.java @@ -2,17 +2,16 @@ package eu.siacs.conversations.utils; import android.os.Parcel; import android.os.Parcelable; - import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; - -import java.util.Collections; -import java.util.List; - import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.services.QuickConversationsService; import eu.siacs.conversations.services.XmppConnectionService; -import eu.siacs.conversations.xmpp.XmppConnection; +import eu.siacs.conversations.xml.Namespace; +import eu.siacs.conversations.xmpp.manager.DiscoManager; +import java.util.Collections; +import java.util.List; +import java.util.Objects; public class EasyOnboardingInvite implements Parcelable { @@ -44,50 +43,53 @@ public class EasyOnboardingInvite implements Parcelable { return 0; } - public static final Creator CREATOR = new Creator() { - @Override - public EasyOnboardingInvite createFromParcel(Parcel in) { - return new EasyOnboardingInvite(in); - } + public static final Creator CREATOR = + new Creator() { + @Override + public EasyOnboardingInvite createFromParcel(Parcel in) { + return new EasyOnboardingInvite(in); + } - @Override - public EasyOnboardingInvite[] newArray(int size) { - return new EasyOnboardingInvite[size]; - } - }; + @Override + public EasyOnboardingInvite[] newArray(int size) { + return new EasyOnboardingInvite[size]; + } + }; public static boolean anyHasSupport(final XmppConnectionService service) { if (QuickConversationsService.isQuicksy()) { return false; } - return getSupportingAccounts(service).size() > 0; - + return !getSupportingAccounts(service).isEmpty(); } public static List getSupportingAccounts(final XmppConnectionService service) { - final ImmutableList.Builder supportingAccountsBuilder = new ImmutableList.Builder<>(); - final List accounts = service == null ? Collections.emptyList() : service.getAccounts(); - for(Account account : accounts) { - final XmppConnection xmppConnection = account.getXmppConnection(); - if (xmppConnection != null && xmppConnection.getFeatures().easyOnboardingInvites()) { + final ImmutableList.Builder supportingAccountsBuilder = + new ImmutableList.Builder<>(); + final List accounts = + service == null ? Collections.emptyList() : service.getAccounts(); + for (final var account : accounts) { + final var connection = account.getXmppConnection(); + final var discoManager = connection.getManager(DiscoManager.class); + if (Objects.nonNull( + discoManager.getAddressForCommand(Namespace.EASY_ONBOARDING_INVITE))) { supportingAccountsBuilder.add(account); } } return supportingAccountsBuilder.build(); } - public String getShareableLink() { return Strings.isNullOrEmpty(landingUrl) ? uri : landingUrl; } - public String getDomain() { return domain; } public interface OnInviteRequested { void inviteRequested(EasyOnboardingInvite invite); + void inviteRequestFailed(String message); } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 66935fe06d2030bcc720900b0eafa845c733b502..c77c5bd357dec7c40c95f4bc40247ed02f31deb5 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -131,12 +131,10 @@ import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.CountDownLatch; @@ -161,7 +159,6 @@ public class XmppConnection implements Runnable { protected final Account account; private final Features features = new Features(this); - private final HashMap commands = new HashMap<>(); private final SparseArray mStanzaQueue = new SparseArray<>(); private final Hashtable>> packetCallbacks = new Hashtable<>(); private final Set advancedStreamFeaturesLoadedListeners = @@ -295,12 +292,6 @@ public class XmppConnection implements Runnable { this.changeState(state, false); } - public Jid getJidForCommand(final String node) { - synchronized (this.commands) { - return this.commands.get(node); - } - } - public void prepareNewConnection() { this.lastConnectionStarted = SystemClock.elapsedRealtime(); this.lastPingSent = SystemClock.elapsedRealtime(); @@ -1957,9 +1948,6 @@ public class XmppConnection implements Runnable { } this.redirectionUrl = null; getManager(DiscoManager.class).clear(); - synchronized (this.commands) { - this.commands.clear(); - } this.loginInfo = null; } @@ -2255,32 +2243,6 @@ public class XmppConnection implements Runnable { }); } - private void discoverCommands() { - // TODO move result handling into DiscoManager too - final var future = - getManager(DiscoManager.class).commands(Entity.discoItem(account.getDomain())); - Futures.addCallback( - future, - new FutureCallback<>() { - @Override - public void onSuccess(Map result) { - synchronized (XmppConnection.this.commands) { - XmppConnection.this.commands.clear(); - XmppConnection.this.commands.putAll(result); - } - } - - @Override - public void onFailure(@NonNull Throwable throwable) { - Log.d( - Config.LOGTAG, - account.getJid().asBareJid() + ": could not fetch commands", - throwable); - } - }, - MoreExecutors.directExecutor()); - } - public boolean isMamPreferenceAlways() { return isMamPreferenceAlways; } @@ -2312,8 +2274,9 @@ public class XmppConnection implements Runnable { if (carbonsManager.hasFeature() && !carbonsManager.isEnabled()) { carbonsManager.enable(); } - if (getFeatures().commands()) { - discoverCommands(); + final var discoManager = getManager(DiscoManager.class); + if (discoManager.hasServerCommands()) { + discoManager.fetchServerCommands(); } } @@ -2998,16 +2961,6 @@ public class XmppConnection implements Runnable { return infoQuery != null && infoQuery.getFeatureStrings().contains(feature); } - public boolean commands() { - return hasDiscoFeature(account.getDomain(), Namespace.COMMANDS); - } - - public boolean easyOnboardingInvites() { - synchronized (commands) { - return commands.containsKey(Namespace.EASY_ONBOARDING_INVITE); - } - } - public boolean blocking() { return connection.getManager(BlockingManager.class).hasFeature(); } diff --git a/src/main/java/eu/siacs/conversations/xmpp/manager/DiscoManager.java b/src/main/java/eu/siacs/conversations/xmpp/manager/DiscoManager.java index 20583c93cf30d69e919bea1b651e08c310ee71eb..0650c4980799647b9fba9f8bcda57dbd7eaeef53 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/manager/DiscoManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/manager/DiscoManager.java @@ -10,6 +10,7 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.io.BaseEncoding; +import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; @@ -91,6 +92,7 @@ public class DiscoManager extends AbstractManager { private final Map entityInformation = new HashMap<>(); private final Map> discoItems = new HashMap<>(); + private final Map commands = new HashMap<>(); public DiscoManager(Context context, XmppConnection connection) { super(context, connection); @@ -447,10 +449,19 @@ public class DiscoManager extends AbstractManager { } } + public Jid getAddressForCommand(final String node) { + synchronized (this.commands) { + return this.commands.get(node); + } + } + public void clear() { synchronized (this.entityInformation) { this.entityInformation.clear(); } + synchronized (this.commands) { + this.commands.clear(); + } } public void clear(final Jid address) { @@ -478,6 +489,34 @@ public class DiscoManager extends AbstractManager { return Iterables.getFirst(items.entrySet(), null); } + public boolean hasServerCommands() { + return hasServerFeature(Namespace.COMMANDS); + } + + public void fetchServerCommands() { + final var future = commands(Entity.discoItem(getAccount().getDomain())); + Futures.addCallback( + future, + new FutureCallback<>() { + @Override + public void onSuccess(Map result) { + synchronized (commands) { + commands.clear(); + commands.putAll(result); + } + } + + @Override + public void onFailure(@androidx.annotation.NonNull Throwable throwable) { + Log.d( + Config.LOGTAG, + getAccount().getJid().asBareJid() + ": could not fetch commands", + throwable); + } + }, + MoreExecutors.directExecutor()); + } + public static final class CapsHashMismatchException extends IllegalStateException { public CapsHashMismatchException(final String message) { super(message);