aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/eu/siacs/conversations/services/XmppConnectionService.java')
-rw-r--r--src/main/java/eu/siacs/conversations/services/XmppConnectionService.java146
1 files changed, 118 insertions, 28 deletions
diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
index fd22b55c..53b60d5f 100644
--- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
@@ -81,7 +81,10 @@ import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.entities.MucOptions.OnRenameListener;
+import eu.siacs.conversations.entities.Presence;
import eu.siacs.conversations.entities.Presences;
+import eu.siacs.conversations.entities.Roster;
+import eu.siacs.conversations.entities.ServiceDiscoveryResult;
import eu.siacs.conversations.entities.Transferable;
import eu.siacs.conversations.entities.TransferablePlaceholder;
import eu.siacs.conversations.generator.IqGenerator;
@@ -247,6 +250,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
private OnKeyStatusUpdated mOnKeyStatusUpdated = null;
private int keyStatusUpdatedListenerCount = 0;
private SecureRandom mRandom;
+ private LruCache<Pair<String,String>,ServiceDiscoveryResult> discoCache = new LruCache<>(20);
private final OnBindListener mOnBindListener = new OnBindListener() {
@Override
@@ -281,7 +285,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
}
List<Conversation> conversations = getConversations();
for (Conversation conversation : conversations) {
- if (conversation.getAccount() == account) {
+ if (conversation.getAccount() == account && conversation.getMode() == Conversation.MODE_SINGLE) {
conversation.startOtrIfNeeded();
sendUnsentMessages(conversation);
}
@@ -333,7 +337,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
}
public PgpEngine getPgpEngine() {
- if (pgpServiceConnection.isBound()) {
+ if (pgpServiceConnection != null && pgpServiceConnection.isBound()) {
if (this.mPgpEngine == null) {
this.mPgpEngine = new PgpEngine(new OpenPgpApi(
getApplicationContext(),
@@ -548,13 +552,13 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
return getPreferences().getBoolean("away_when_screen_off", false);
}
- private int getTargetPresence() {
+ private Presence.Status getTargetPresence() {
if (xaOnSilentMode() && isPhoneSilenced()) {
- return Presences.XA;
+ return Presence.Status.XA;
} else if (awayWhenScreenOff() && !isInteractive()) {
- return Presences.AWAY;
+ return Presence.Status.AWAY;
} else {
- return Presences.ONLINE;
+ return Presence.Status.ONLINE;
}
}
@@ -936,11 +940,11 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
private void sendUnsentMessages(final Conversation conversation) {
conversation.findWaitingMessages(new Conversation.OnMessageFound() {
- @Override
- public void onMessageFound(Message message) {
- resendMessage(message, true);
- }
- });
+ @Override
+ public void onMessageFound(Message message) {
+ resendMessage(message, true);
+ }
+ });
}
public void resendMessage(final Message message, final boolean delay) {
@@ -1163,25 +1167,28 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
}
}
Collections.sort(list, new Comparator<Conversation>() {
- @Override
- public int compare(Conversation lhs, Conversation rhs) {
- Message left = lhs.getLatestMessage();
- Message right = rhs.getLatestMessage();
- if (left.getTimeSent() > right.getTimeSent()) {
- return -1;
- } else if (left.getTimeSent() < right.getTimeSent()) {
- return 1;
- } else {
- return 0;
- }
- }
- });
+ @Override
+ public int compare(Conversation lhs, Conversation rhs) {
+ Message left = lhs.getLatestMessage();
+ Message right = rhs.getLatestMessage();
+ if (left.getTimeSent() > right.getTimeSent()) {
+ return -1;
+ } else if (left.getTimeSent() < right.getTimeSent()) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ });
}
public void loadMoreMessages(final Conversation conversation, final long timestamp, final OnMoreMessagesLoaded callback) {
if (XmppConnectionService.this.getMessageArchiveService().queryInProgress(conversation, callback)) {
Logging.d("mam", "Query in progress");
return;
+ } else if (timestamp == 0) {
+ Logging.d("mam", "Query stopped due to timestamp");
+ return;
}
//TODO Create a separate class for this runnable to store if messages are getting loaded or not. Not really a good idea to do this in the callback.
Logging.d(Config.LOGTAG, "load more messages for " + conversation.getName() + " prior to " + MessageGenerator.getTimestamp(timestamp));
@@ -1201,7 +1208,8 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
checkDeletedFiles(conversation);
callback.onMoreMessagesLoaded(messages.size(), conversation);
} else if (conversation.hasMessagesLeftOnServer()
- && account.isOnlineAndConnected()) {
+ && account.isOnlineAndConnected()
+ && conversation.getLastClearHistory() == 0) {
Logging.d("mam", "mam activate, account online and connected and messages left on server");
if ((conversation.getMode() == Conversation.MODE_SINGLE && account.getXmppConnection().getFeatures().mam())
|| (conversation.getMode() == Conversation.MODE_MULTI && conversation.getMucOptions().mamSupport())) {
@@ -1448,7 +1456,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
databaseBackend.deleteAccount(account);
}
};
- ConversationsPlusApplication.executeDatabaseOperation(runnable);
+ mDatabaseExecutor.execute(runnable);
this.accounts.remove(account);
updateAccountUi();
getNotificationService().updateErrorNotification();
@@ -1753,6 +1761,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
if (conversation.getMucOptions().mamSupport()) {
getMessageArchiveService().catchupMUC(conversation);
}
+ sendUnsentMessages(conversation);
}
@Override
@@ -2164,7 +2173,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
packet.setFrom(account.getJid());
MessageGenerator.addMessageHints(packet);
packet.setAttribute("to", otrSession.getSessionID().getAccountID() + "/"
- + otrSession.getSessionID().getUserID());
+ + otrSession.getSessionID().getUserID());
try {
packet.setBody(otrSession
.transformSending(CryptoHelper.FILETRANSFER
@@ -2726,13 +2735,94 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
if (packet.getType() == IqPacket.TYPE.ERROR) {
- Log.d(Config.LOGTAG,account.getJid().toBareJid()+": could not publish nick");
+ Logging.d(Config.LOGTAG,account.getJid().toBareJid()+": could not publish nick");
}
}
});
}
}
+ private ServiceDiscoveryResult getCachedServiceDiscoveryResult(Pair<String,String> key) {
+ ServiceDiscoveryResult result = discoCache.get(key);
+ if (result != null) {
+ return result;
+ } else {
+ result = databaseBackend.findDiscoveryResult(key.first, key.second);
+ if (result != null) {
+ discoCache.put(key, result);
+ }
+ return result;
+ }
+ }
+
+ public void fetchCaps(Account account, final Jid jid, final Presence presence) {
+ final Pair<String,String> key = new Pair<>(presence.getHash(), presence.getVer());
+ ServiceDiscoveryResult disco = getCachedServiceDiscoveryResult(key);
+ if (disco != null) {
+ presence.setServiceDiscoveryResult(disco);
+ } else {
+ if (!account.inProgressDiscoFetches.contains(key)) {
+ account.inProgressDiscoFetches.add(key);
+ IqPacket request = new IqPacket(IqPacket.TYPE.GET);
+ request.setTo(jid);
+ request.query("http://jabber.org/protocol/disco#info");
+ Log.d(Config.LOGTAG,account.getJid().toBareJid()+": making disco request for "+key.second+" to "+jid);
+ sendIqPacket(account, request, new OnIqPacketReceived() {
+ @Override
+ public void onIqPacketReceived(Account account, IqPacket discoPacket) {
+ if (discoPacket.getType() == IqPacket.TYPE.RESULT) {
+ ServiceDiscoveryResult disco = new ServiceDiscoveryResult(discoPacket);
+ if (presence.getVer().equals(disco.getVer())) {
+ databaseBackend.insertDiscoveryResult(disco);
+ injectServiceDiscorveryResult(account.getRoster(), presence.getHash(), presence.getVer(), disco);
+ } else {
+ Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": mismatch in caps for contact " + jid+" "+presence.getVer()+" vs "+disco.getVer());
+ }
+ }
+ account.inProgressDiscoFetches.remove(key);
+ }
+ });
+ }
+ }
+ }
+
+ private void injectServiceDiscorveryResult(Roster roster, String hash, String ver, ServiceDiscoveryResult disco) {
+ for(Contact contact : roster.getContacts()) {
+ for(Presence presence : contact.getPresences().getPresences().values()) {
+ if (hash.equals(presence.getHash()) && ver.equals(presence.getVer())) {
+ presence.setServiceDiscoveryResult(disco);
+ }
+ }
+ }
+ }
+
+ public void fetchMamPreferences(Account account, final OnMamPreferencesFetched callback) {
+ IqPacket request = new IqPacket(IqPacket.TYPE.GET);
+ request.addChild("prefs","urn:xmpp:mam:0");
+ sendIqPacket(account, request, new OnIqPacketReceived() {
+ @Override
+ public void onIqPacketReceived(Account account, IqPacket packet) {
+ Element prefs = packet.findChild("prefs","urn:xmpp:mam:0");
+ if (packet.getType() == IqPacket.TYPE.RESULT && prefs != null) {
+ callback.onPreferencesFetched(prefs);
+ } else {
+ callback.onPreferencesFetchFailed();
+ }
+ }
+ });
+ }
+
+ public interface OnMamPreferencesFetched {
+ void onPreferencesFetched(Element prefs);
+ void onPreferencesFetchFailed();
+ }
+
+ public void pushMamPreferences(Account account, Element prefs) {
+ IqPacket set = new IqPacket(IqPacket.TYPE.SET);
+ set.addChild(prefs);
+ sendIqPacket(account, set, null);
+ }
+
public interface OnAccountCreated {
void onAccountCreated(Account account);