1package im.conversations.android.xmpp.processor;
2
3import android.util.Log;
4import androidx.annotation.NonNull;
5import com.google.common.base.Strings;
6import com.google.common.util.concurrent.FutureCallback;
7import com.google.common.util.concurrent.Futures;
8import com.google.common.util.concurrent.MoreExecutors;
9import eu.siacs.conversations.Config;
10import eu.siacs.conversations.entities.Account;
11import eu.siacs.conversations.services.XmppConnectionService;
12import eu.siacs.conversations.xmpp.XmppConnection;
13import eu.siacs.conversations.xmpp.manager.BookmarkManager;
14import eu.siacs.conversations.xmpp.manager.HttpUploadManager;
15import eu.siacs.conversations.xmpp.manager.MessageDisplayedSynchronizationManager;
16import eu.siacs.conversations.xmpp.manager.MultiUserChatManager;
17import eu.siacs.conversations.xmpp.manager.NickManager;
18import eu.siacs.conversations.xmpp.manager.OfflineMessagesManager;
19import eu.siacs.conversations.xmpp.manager.PresenceManager;
20import eu.siacs.conversations.xmpp.manager.RosterManager;
21
22public class BindProcessor extends XmppConnection.Delegate implements Runnable {
23
24 private final XmppConnectionService service;
25
26 public BindProcessor(final XmppConnectionService service, final XmppConnection connection) {
27 super(service, connection);
28 this.service = service;
29 }
30
31 @Override
32 public void run() {
33 final var account = connection.getAccount();
34 final var features = connection.getFeatures();
35 final boolean loggedInSuccessfully =
36 account.setOption(Account.OPTION_LOGGED_IN_SUCCESSFULLY, true);
37 final boolean sosModified;
38 final var sos = features.getServiceOutageStatus();
39 if (sos != null) {
40 Log.d(Config.LOGTAG, account.getJid().asBareJid() + " server has SOS on " + sos);
41 sosModified = account.setKey(Account.KEY_SOS_URL, sos.toString());
42 } else {
43 sosModified = false;
44 }
45 final boolean gainedFeature =
46 account.setOption(
47 Account.OPTION_HTTP_UPLOAD_AVAILABLE,
48 getManager(HttpUploadManager.class).isAvailableForSize(0));
49 if (loggedInSuccessfully || gainedFeature || sosModified) {
50 service.databaseBackend.updateAccount(account);
51 }
52
53 if (loggedInSuccessfully) {
54 final String displayName = account.getDisplayName();
55 if (!Strings.isNullOrEmpty(displayName)) {
56 Log.d(
57 Config.LOGTAG,
58 account.getJid().asBareJid()
59 + ": display name wasn't empty on first log in. publishing");
60 getManager(NickManager.class).publish(displayName);
61 }
62 }
63
64 getManager(RosterManager.class).clearPresences();
65 getManager(MultiUserChatManager.class).clearInProgress();
66 service.getJingleConnectionManager().notifyRebound(account);
67 service.getQuickConversationsService().considerSyncBackground(false);
68
69 getManager(RosterManager.class).request();
70 getManager(BookmarkManager.class).request();
71
72 if (features.mds()) {
73 getManager(MessageDisplayedSynchronizationManager.class).fetch();
74 } else {
75 Log.d(Config.LOGTAG, account.getJid() + ": server has no support for mds");
76 }
77 final var offlineManager = getManager(OfflineMessagesManager.class);
78 final boolean bind2 = features.bind2();
79 final boolean flexible = offlineManager.hasFeature();
80 final boolean catchup = service.getMessageArchiveService().inCatchup(account);
81 final boolean trackOfflineMessageRetrieval;
82 if (!bind2 && flexible && catchup && connection.isMamPreferenceAlways()) {
83 trackOfflineMessageRetrieval = false;
84 Futures.addCallback(
85 offlineManager.purge(),
86 new FutureCallback<Void>() {
87 @Override
88 public void onSuccess(Void result) {
89 Log.d(
90 Config.LOGTAG,
91 account.getJid().asBareJid()
92 + ": successfully purged offline messages");
93 }
94
95 @Override
96 public void onFailure(@NonNull Throwable t) {
97 Log.d(Config.LOGTAG, "could not purge offline messages", t);
98 }
99 },
100 MoreExecutors.directExecutor());
101 } else {
102 trackOfflineMessageRetrieval = true;
103 }
104 getManager(PresenceManager.class).available();
105 connection.trackOfflineMessageRetrieval(trackOfflineMessageRetrieval);
106 if (service.getPushManagementService().available(account)) {
107 service.getPushManagementService().registerPushTokenOnServer(account);
108 }
109 service.connectMultiModeConversations(account);
110 getManager(RosterManager.class).syncDirtyContacts();
111
112 service.getUnifiedPushBroker().renewUnifiedPushEndpointsOnBind(account);
113 }
114}