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.java277
1 files changed, 138 insertions, 139 deletions
diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
index 2f44375e..b7ca699c 100644
--- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
@@ -32,20 +32,14 @@ import net.java.otr4j.session.SessionStatus;
import org.openintents.openpgp.util.OpenPgpApi;
import org.openintents.openpgp.util.OpenPgpServiceConnection;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.OutputStream;
import java.math.BigInteger;
import java.security.SecureRandom;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
-import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
-import java.util.TimeZone;
import java.util.concurrent.CopyOnWriteArrayList;
import de.duenndns.ssl.MemorizingTrustManager;
@@ -97,7 +91,7 @@ import eu.siacs.conversations.xmpp.stanzas.IqPacket;
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
-public class XmppConnectionService extends Service {
+public class XmppConnectionService extends Service implements OnPhoneContactsLoadedListener {
public static String ACTION_CLEAR_NOTIFICATION = "clear_notification";
private static String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts";
@@ -126,7 +120,7 @@ public class XmppConnectionService extends Service {
conversation.resetOtrSession();
}
if (online && (contact.getPresences().size() == 1)) {
- sendUnsendMessages(conversation);
+ sendUnsentMessages(conversation);
}
}
}
@@ -147,6 +141,7 @@ public class XmppConnectionService extends Service {
private HttpConnectionManager mHttpConnectionManager = new HttpConnectionManager(
this);
private AvatarService mAvatarService = new AvatarService(this);
+ private MessageArchiveService mMessageArchiveService = new MessageArchiveService(this);
private OnConversationUpdate mOnConversationUpdate = null;
private Integer convChangedListenerCount = 0;
private OnAccountUpdate mOnAccountUpdate = null;
@@ -165,12 +160,13 @@ public class XmppConnectionService extends Service {
for (Conversation conversation : account.pendingConferenceJoins) {
joinMuc(conversation);
}
+ mMessageArchiveService.executePendingQueries(account);
mJingleConnectionManager.cancelInTransmission();
List<Conversation> conversations = getConversations();
for (Conversation conversation : conversations) {
if (conversation.getAccount() == account) {
conversation.startOtrIfNeeded();
- sendUnsendMessages(conversation);
+ sendUnsentMessages(conversation);
}
}
if (connection != null && connection.getFeatures().csi()) {
@@ -209,6 +205,7 @@ public class XmppConnectionService extends Service {
getNotificationService().updateErrorNotification();
}
};
+
private int accountChangedListenerCount = 0;
private OnRosterUpdate mOnRosterUpdate = null;
private int rosterChangedListenerCount = 0;
@@ -260,15 +257,14 @@ public class XmppConnectionService extends Service {
@Override
public void onMessageAcknowledged(Account account, String uuid) {
- for (Conversation conversation : getConversations()) {
+ for (final Conversation conversation : getConversations()) {
if (conversation.getAccount() == account) {
- for (Message message : conversation.getMessages()) {
- if ((message.getStatus() == Message.STATUS_UNSEND || message
- .getStatus() == Message.STATUS_WAITING)
- && message.getUuid().equals(uuid)) {
- markMessage(message, Message.STATUS_SEND);
- return;
- }
+ Message message = conversation.findUnsentMessageWithUuid(uuid);
+ if (message != null) {
+ markMessage(message, Message.STATUS_SEND);
+ if (conversation.setLastMessageTransmitted(System.currentTimeMillis())) {
+ databaseBackend.updateConversation(conversation);
+ }
}
}
}
@@ -276,6 +272,7 @@ public class XmppConnectionService extends Service {
};
private LruCache<String, Bitmap> mBitmapCache;
private IqGenerator mIqGenerator = new IqGenerator(this);
+ private Thread mPhoneContactMergerThread;
public PgpEngine getPgpEngine() {
if (pgpServiceConnection.isBound()) {
@@ -384,7 +381,7 @@ public class XmppConnectionService extends Service {
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null && intent.getAction() != null) {
if (intent.getAction().equals(ACTION_MERGE_PHONE_CONTACTS)) {
- mergePhoneContactsWithRoster();
+ PhoneHelper.loadPhoneContacts(getApplicationContext(), new ArrayList<Bundle>(), this);
return START_STICKY;
} else if (intent.getAction().equals(Intent.ACTION_SHUTDOWN)) {
logoutAndSave();
@@ -496,7 +493,7 @@ public class XmppConnectionService extends Service {
this.databaseBackend.readRoster(account.getRoster());
}
initConversations();
- this.mergePhoneContactsWithRoster();
+ PhoneHelper.loadPhoneContacts(getApplicationContext(),new ArrayList<Bundle>(), this);
getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, contactObserver);
this.fileObserver.startWatching();
@@ -589,8 +586,8 @@ public class XmppConnectionService extends Service {
connection.setOnUnregisteredIqPacketReceivedListener(this.mIqParser);
connection.setOnJinglePacketReceivedListener(this.jingleListener);
connection.setOnBindListener(this.mOnBindListener);
- connection
- .setOnMessageAcknowledgeListener(this.mOnMessageAcknowledgedListener);
+ connection.setOnMessageAcknowledgeListener(this.mOnMessageAcknowledgedListener);
+ connection.addOnAdvancedStreamFeaturesAvailableListener(this.mMessageArchiveService);
return connection;
}
@@ -641,12 +638,22 @@ public class XmppConnectionService extends Service {
}
} else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
message.getConversation().endOtrIfNeeded();
- failWaitingOtrMessages(message.getConversation());
+ message.getConversation().findUnsentMessagesWithOtrEncryption(new Conversation.OnMessageFound() {
+ @Override
+ public void onMessageFound(Message message) {
+ markMessage(message,Message.STATUS_SEND_FAILED);
+ }
+ });
packet = mMessageGenerator.generatePgpChat(message);
send = true;
} else {
message.getConversation().endOtrIfNeeded();
- failWaitingOtrMessages(message.getConversation());
+ message.getConversation().findUnsentMessagesWithOtrEncryption(new Conversation.OnMessageFound() {
+ @Override
+ public void onMessageFound(Message message) {
+ markMessage(message,Message.STATUS_SEND_FAILED);
+ }
+ });
packet = mMessageGenerator.generateChat(message);
send = true;
}
@@ -689,13 +696,14 @@ public class XmppConnectionService extends Service {
updateConversationUi();
}
- private void sendUnsendMessages(Conversation conversation) {
- for (int i = 0; i < conversation.getMessages().size(); ++i) {
- int status = conversation.getMessages().get(i).getStatus();
- if (status == Message.STATUS_WAITING) {
- resendMessage(conversation.getMessages().get(i));
+ private void sendUnsentMessages(Conversation conversation) {
+ conversation.findWaitingMessages(new Conversation.OnMessageFound() {
+
+ @Override
+ public void onMessageFound(Message message) {
+ resendMessage(message);
}
- }
+ });
}
private void resendMessage(Message message) {
@@ -839,39 +847,43 @@ public class XmppConnectionService extends Service {
sendIqPacket(account, iqPacket, null);
}
- private void mergePhoneContactsWithRoster() {
- PhoneHelper.loadPhoneContacts(getApplicationContext(),
- new OnPhoneContactsLoadedListener() {
- @Override
- public void onPhoneContactsLoaded(List<Bundle> phoneContacts) {
- for (Account account : accounts) {
- account.getRoster().clearSystemAccounts();
+ public void onPhoneContactsLoaded(final List<Bundle> phoneContacts) {
+ if (mPhoneContactMergerThread != null) {
+ mPhoneContactMergerThread.interrupt();
+ }
+ mPhoneContactMergerThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ Log.d(Config.LOGTAG,"start merging phone contacts with roster");
+ for (Account account : accounts) {
+ account.getRoster().clearSystemAccounts();
+ for (Bundle phoneContact : phoneContacts) {
+ if (Thread.interrupted()) {
+ Log.d(Config.LOGTAG,"interrupted merging phone contacts");
+ return;
}
- for (Bundle phoneContact : phoneContacts) {
- for (Account account : accounts) {
- Jid jid;
- try {
- jid = Jid.fromString(phoneContact.getString("jid"));
- } catch (final InvalidJidException e) {
- // TODO: Warn if contact import fails here?
- break;
- }
- final Contact contact = account.getRoster()
- .getContact(jid);
- String systemAccount = phoneContact
- .getInt("phoneid")
- + "#"
- + phoneContact.getString("lookup");
- contact.setSystemAccount(systemAccount);
- contact.setPhotoUri(phoneContact
- .getString("photouri"));
- contact.setSystemName(phoneContact
- .getString("displayname"));
- getAvatarService().clear(contact);
- }
+ Jid jid;
+ try {
+ jid = Jid.fromString(phoneContact.getString("jid"));
+ } catch (final InvalidJidException e) {
+ break;
}
+ final Contact contact = account.getRoster()
+ .getContact(jid);
+ String systemAccount = phoneContact.getInt("phoneid")
+ + "#"
+ + phoneContact.getString("lookup");
+ contact.setSystemAccount(systemAccount);
+ contact.setPhotoUri(phoneContact.getString("photouri"));
+ getAvatarService().clear(contact);
+ contact.setSystemName(phoneContact.getString("displayname"));
}
- });
+ }
+ Log.d(Config.LOGTAG,"finished merging phone contacts");
+ updateAccountUi();
+ }
+ });
+ mPhoneContactMergerThread.start();
}
private void initConversations() {
@@ -895,28 +907,26 @@ public class XmppConnectionService extends Service {
}
private void checkDeletedFiles(Conversation conversation) {
- for (Message message : conversation.getMessages()) {
- if ((message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE)
- && message.getEncryption() != Message.ENCRYPTION_PGP) {
+ conversation.findMessagesWithFiles(new Conversation.OnMessageFound() {
+
+ @Override
+ public void onMessageFound(Message message) {
if (!getFileBackend().isFileAvailable(message)) {
message.setDownloadable(new DownloadablePlaceholder(Downloadable.STATUS_DELETED));
}
- }
- }
+ }
+ });
}
private void markFileDeleted(String uuid) {
for (Conversation conversation : getConversations()) {
- for (Message message : conversation.getMessages()) {
- if (message.getType() == Message.TYPE_IMAGE
- && message.getEncryption() != Message.ENCRYPTION_PGP
- && message.getUuid().equals(uuid)) {
- if (!getFileBackend().isFileAvailable(message)) {
- message.setDownloadable(new DownloadablePlaceholder(Downloadable.STATUS_DELETED));
- updateConversationUi();
- }
- return;
- }
+ Message message = conversation.findMessageWithFileAndUuid(uuid);
+ if (message != null) {
+ if (!getFileBackend().isFileAvailable(message)) {
+ message.setDownloadable(new DownloadablePlaceholder(Downloadable.STATUS_DELETED));
+ updateConversationUi();
+ }
+ return;
}
}
}
@@ -953,6 +963,9 @@ public class XmppConnectionService extends Service {
}
public int loadMoreMessages(Conversation conversation, long timestamp) {
+ if (this.getMessageArchiveService().queryInProgress(conversation)) {
+ return 0;
+ }
List<Message> messages = databaseBackend.getMessages(conversation, 50,
timestamp);
for (Message message : messages) {
@@ -990,8 +1003,11 @@ public class XmppConnectionService extends Service {
return null;
}
- public Conversation findOrCreateConversation(final Account account, final Jid jid,
- final boolean muc) {
+ public Conversation findOrCreateConversation(final Account account, final Jid jid,final boolean muc) {
+ return this.findOrCreateConversation(account,jid,muc,null);
+ }
+
+ public Conversation findOrCreateConversation(final Account account, final Jid jid,final boolean muc, final MessageArchiveService.Query query) {
synchronized (this.conversations) {
Conversation conversation = find(account, jid);
if (conversation != null) {
@@ -1025,6 +1041,13 @@ public class XmppConnectionService extends Service {
}
this.databaseBackend.createConversation(conversation);
}
+ if (query == null) {
+ this.mMessageArchiveService.query(conversation);
+ } else {
+ if (query.getConversation() == null) {
+ this.mMessageArchiveService.query(conversation,query.getStart());
+ }
+ }
this.conversations.add(conversation);
updateConversationUi();
return conversation;
@@ -1051,12 +1074,6 @@ public class XmppConnectionService extends Service {
}
}
- public void clearConversationHistory(Conversation conversation) {
- this.databaseBackend.deleteMessagesInConversation(conversation);
- conversation.getMessages().clear();
- updateConversationUi();
- }
-
public void createAccount(Account account) {
account.initOtrEngine(this);
databaseBackend.createAccount(account);
@@ -1251,27 +1268,16 @@ public class XmppConnectionService extends Service {
PresencePacket packet = new PresencePacket();
packet.setFrom(conversation.getAccount().getJid());
packet.setTo(joinJid);
- Element x = new Element("x");
- x.setAttribute("xmlns", "http://jabber.org/protocol/muc");
+ Element x = packet.addChild("x","http://jabber.org/protocol/muc");
if (conversation.getMucOptions().getPassword() != null) {
- Element password = x.addChild("password");
- password.setContent(conversation.getMucOptions().getPassword());
+ x.addChild("password").setContent(conversation.getMucOptions().getPassword());
}
+ x.addChild("history").setAttribute("since",PresenceGenerator.getTimestamp(conversation.getLastMessageTransmitted()));
String sig = account.getPgpSignature();
if (sig != null) {
packet.addChild("status").setContent("online");
packet.addChild("x", "jabber:x:signed").setContent(sig);
}
- if (conversation.getMessages().size() != 0) {
- final SimpleDateFormat mDateFormat = new SimpleDateFormat(
- "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
- mDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
- Date date = new Date(conversation.getLatestMessage()
- .getTimeSent() + 1000);
- x.addChild("history").setAttribute("since",
- mDateFormat.format(date));
- }
- packet.addChild(x);
sendPresencePacket(account, packet);
if (!joinJid.equals(conversation.getContactJid())) {
conversation.setContactJid(joinJid);
@@ -1315,7 +1321,7 @@ public class XmppConnectionService extends Service {
@Override
public void onFailure() {
- callback.error(R.string.nick_in_use,conversation);
+ callback.error(R.string.nick_in_use, conversation);
}
});
@@ -1528,36 +1534,35 @@ public class XmppConnectionService extends Service {
}
public void onOtrSessionEstablished(Conversation conversation) {
- Account account = conversation.getAccount();
- List<Message> messages = conversation.getMessages();
- Session otrSession = conversation.getOtrSession();
+ final Account account = conversation.getAccount();
+ final Session otrSession = conversation.getOtrSession();
Log.d(Config.LOGTAG,
account.getJid().toBareJid() + " otr session established with "
- + conversation.getContactJid() + "/"
- + otrSession.getSessionID().getUserID());
- for (Message msg : messages) {
- if ((msg.getStatus() == Message.STATUS_UNSEND || msg.getStatus() == Message.STATUS_WAITING)
- && (msg.getEncryption() == Message.ENCRYPTION_OTR)) {
+ + conversation.getContactJid() + "/"
+ + otrSession.getSessionID().getUserID());
+ conversation.findUnsentMessagesWithOtrEncryption(new Conversation.OnMessageFound() {
+
+ @Override
+ public void onMessageFound(Message message) {
SessionID id = otrSession.getSessionID();
try {
- msg.setCounterpart(Jid.fromString(id.getAccountID() + "/" + id.getUserID()));
+ message.setCounterpart(Jid.fromString(id.getAccountID() + "/" + id.getUserID()));
} catch (InvalidJidException e) {
- break;
+ return;
}
- if (msg.getType() == Message.TYPE_TEXT) {
- MessagePacket outPacket = mMessageGenerator
- .generateOtrChat(msg, true);
+ if (message.getType() == Message.TYPE_TEXT) {
+ MessagePacket outPacket = mMessageGenerator.generateOtrChat(message, true);
if (outPacket != null) {
- msg.setStatus(Message.STATUS_SEND);
- databaseBackend.updateMessage(msg);
+ message.setStatus(Message.STATUS_SEND);
+ databaseBackend.updateMessage(message);
sendMessagePacket(account, outPacket);
}
- } else if (msg.getType() == Message.TYPE_IMAGE || msg.getType() == Message.TYPE_FILE) {
- mJingleConnectionManager.createNewConnection(msg);
+ } else if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE) {
+ mJingleConnectionManager.createNewConnection(message);
}
- }
- }
- updateConversationUi();
+ updateConversationUi();
+ }
+ });
}
public boolean renewSymmetricKey(Conversation conversation) {
@@ -1812,12 +1817,13 @@ public class XmppConnectionService extends Service {
public void resetSendingToWaiting(Account account) {
for (Conversation conversation : getConversations()) {
if (conversation.getAccount() == account) {
- for (Message message : conversation.getMessages()) {
- if (message.getType() != Message.TYPE_IMAGE
- && message.getStatus() == Message.STATUS_UNSEND) {
+ conversation.findUnsentTextMessages(new Conversation.OnMessageFound() {
+
+ @Override
+ public void onMessageFound(Message message) {
markMessage(message, Message.STATUS_WAITING);
- }
- }
+ }
+ });
}
}
}
@@ -1842,15 +1848,13 @@ public class XmppConnectionService extends Service {
if (uuid == null) {
return false;
} else {
- for (Message message : conversation.getMessages()) {
- if (uuid.equals(message.getUuid())
- || (message.getStatus() >= Message.STATUS_SEND && uuid
- .equals(message.getRemoteMsgId()))) {
- markMessage(message, status);
- return true;
- }
+ Message message = conversation.findSentMessageWithUuid(uuid);
+ if (message!=null) {
+ markMessage(message,status);
+ return true;
+ } else {
+ return false;
}
- return false;
}
}
@@ -1944,15 +1948,6 @@ public class XmppConnectionService extends Service {
}
}
- public void failWaitingOtrMessages(Conversation conversation) {
- for (Message message : conversation.getMessages()) {
- if (message.getEncryption() == Message.ENCRYPTION_OTR
- && message.getStatus() == Message.STATUS_WAITING) {
- markMessage(message, Message.STATUS_SEND_FAILED);
- }
- }
- }
-
public SecureRandom getRNG() {
return this.mRandom;
}
@@ -2049,6 +2044,10 @@ public class XmppConnectionService extends Service {
return this.mJingleConnectionManager;
}
+ public MessageArchiveService getMessageArchiveService() {
+ return this.mMessageArchiveService;
+ }
+
public List<Contact> findContacts(Jid jid) {
ArrayList<Contact> contacts = new ArrayList<>();
for (Account account : getAccounts()) {