From af5445ad103e1eda066924c816eef4067a4d7228 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Sun, 21 Jan 2018 14:57:30 +0100 Subject: sent message receipts after mam catchup --- .../pixart/messenger/entities/ReceiptRequest.java | 75 ++++++++++++++++++++++ .../messenger/generator/MessageGenerator.java | 10 +++ .../de/pixart/messenger/parser/MessageParser.java | 66 +++++++++++++------ .../messenger/services/MessageArchiveService.java | 16 ++++- 4 files changed, 146 insertions(+), 21 deletions(-) create mode 100644 src/main/java/de/pixart/messenger/entities/ReceiptRequest.java (limited to 'src/main/java/de/pixart/messenger') diff --git a/src/main/java/de/pixart/messenger/entities/ReceiptRequest.java b/src/main/java/de/pixart/messenger/entities/ReceiptRequest.java new file mode 100644 index 000000000..440f13d6f --- /dev/null +++ b/src/main/java/de/pixart/messenger/entities/ReceiptRequest.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, Daniel Gultsch All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package de.pixart.messenger.entities; + +import de.pixart.messenger.xmpp.jid.Jid; + +public class ReceiptRequest { + + private final Jid jid; + private final String id; + + public ReceiptRequest(Jid jid, String id) { + if (id == null) { + throw new IllegalArgumentException("id must not be null"); + } + if (jid == null) { + throw new IllegalArgumentException("jid must not be null"); + } + this.jid = jid.toBareJid(); + this.id = id; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ReceiptRequest that = (ReceiptRequest) o; + + if (!jid.equals(that.jid)) return false; + return id.equals(that.id); + } + + @Override + public int hashCode() { + int result = jid.hashCode(); + result = 31 * result + id.hashCode(); + return result; + } + + public String getId() { + return id; + } + + public Jid getJid() { + return jid; + } +} \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/generator/MessageGenerator.java b/src/main/java/de/pixart/messenger/generator/MessageGenerator.java index b795997e8..0c91302c7 100644 --- a/src/main/java/de/pixart/messenger/generator/MessageGenerator.java +++ b/src/main/java/de/pixart/messenger/generator/MessageGenerator.java @@ -239,9 +239,19 @@ public class MessageGenerator extends AbstractGenerator { for (String namespace : namespaces) { receivedPacket.addChild("received", namespace).setAttribute("id", originalMessage.getId()); } + receivedPacket.addChild("store", "urn:xmpp:hints"); return receivedPacket; } + public MessagePacket received(Account account, Jid to, String id) { + MessagePacket packet = new MessagePacket(); + packet.setFrom(account.getJid()); + packet.setTo(to); + packet.addChild("received", "urn:xmpp:receipts").setAttribute("id", id); + packet.addChild("store", "urn:xmpp:hints"); + return packet; + } + public MessagePacket generateOtrError(Jid to, String id, String errorText) { MessagePacket packet = new MessagePacket(); packet.setType(MessagePacket.TYPE_ERROR); diff --git a/src/main/java/de/pixart/messenger/parser/MessageParser.java b/src/main/java/de/pixart/messenger/parser/MessageParser.java index b19b30fa8..7ec1f68d3 100644 --- a/src/main/java/de/pixart/messenger/parser/MessageParser.java +++ b/src/main/java/de/pixart/messenger/parser/MessageParser.java @@ -30,6 +30,7 @@ import de.pixart.messenger.entities.Message; import de.pixart.messenger.entities.MucOptions; import de.pixart.messenger.entities.Presence; import de.pixart.messenger.entities.ReadByMarker; +import de.pixart.messenger.entities.ReceiptRequest; import de.pixart.messenger.entities.ServiceDiscoveryResult; import de.pixart.messenger.http.HttpConnectionManager; import de.pixart.messenger.services.MessageArchiveService; @@ -560,8 +561,13 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece extractChatState(mXmppConnectionService.find(account, counterpart.toBareJid()), isTypeGroupChat, packet); mXmppConnectionService.updateMessage(replacedMessage, uuid); mXmppConnectionService.getNotificationService().updateNotification(false); - if (mXmppConnectionService.confirmMessages() && (replacedMessage.trusted() || replacedMessage.getType() == Message.TYPE_PRIVATE) && remoteMsgId != null && !isForwarded && !isTypeGroupChat) { - sendMessageReceipts(account, packet); + if (mXmppConnectionService.confirmMessages() + && replacedMessage.getStatus() == Message.STATUS_RECEIVED + && (replacedMessage.trusted() || replacedMessage.getType() == Message.TYPE_PRIVATE) + && remoteMsgId != null + && (!isForwarded || query != null) + && !isTypeGroupChat) { + processMessageReceipts(account, packet, query); } if (replacedMessage.getEncryption() == Message.ENCRYPTION_PGP) { conversation.getAccount().getPgpDecryptionService().discard(replacedMessage); @@ -633,8 +639,13 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece mXmppConnectionService.updateConversationUi(); } - if (mXmppConnectionService.confirmMessages() && (message.trusted() || message.getType() == Message.TYPE_PRIVATE) && remoteMsgId != null && !isForwarded && !isTypeGroupChat) { - sendMessageReceipts(account, packet); + if (mXmppConnectionService.confirmMessages() + && message.getStatus() == Message.STATUS_RECEIVED + && (message.trusted() || message.getType() == Message.TYPE_PRIVATE) + && remoteMsgId != null + && (!isForwarded || query != null) + && !isTypeGroupChat) { + processMessageReceipts(account, packet, query); } if (message.getStatus() == Message.STATUS_RECEIVED @@ -721,8 +732,15 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece if (received == null) { received = packet.findChild("received", "urn:xmpp:receipts"); } - if (received != null && !packet.fromAccount(account)) { - mXmppConnectionService.markMessage(account, from.toBareJid(), received.getAttribute("id"), Message.STATUS_SEND_RECEIVED); + if (received != null) { + String id = received.getAttribute("id"); + if (packet.fromAccount(account)) { + if (query != null && id != null && packet.getTo() != null) { + query.pendingReceiptRequests.remove(new ReceiptRequest(packet.getTo(), id)); + } + } else { + mXmppConnectionService.markMessage(account, from.toBareJid(), received.getAttribute("id"), Message.STATUS_SEND_RECEIVED); + } } Element displayed = packet.findChild("displayed", "urn:xmpp:chat-markers:0"); if (displayed != null) { @@ -788,20 +806,28 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece return result != null ? result : fallback; } - private void sendMessageReceipts(Account account, MessagePacket packet) { - ArrayList receiptsNamespaces = new ArrayList<>(); - if (packet.hasChild("markable", "urn:xmpp:chat-markers:0")) { - receiptsNamespaces.add("urn:xmpp:chat-markers:0"); - } - if (packet.hasChild("request", "urn:xmpp:receipts")) { - receiptsNamespaces.add("urn:xmpp:receipts"); - } - if (receiptsNamespaces.size() > 0) { - MessagePacket receipt = mXmppConnectionService.getMessageGenerator().received(account, - packet, - receiptsNamespaces, - packet.getType()); - mXmppConnectionService.sendMessagePacket(account, receipt); + private void processMessageReceipts(Account account, MessagePacket packet, MessageArchiveService.Query query) { + final boolean markable = packet.hasChild("markable", "urn:xmpp:chat-markers:0"); + final boolean request = packet.hasChild("request", "urn:xmpp:receipts"); + if (query == null) { + final ArrayList receiptsNamespaces = new ArrayList<>(); + if (markable) { + receiptsNamespaces.add("urn:xmpp:chat-markers:0"); + } + if (request) { + receiptsNamespaces.add("urn:xmpp:receipts"); + } + if (receiptsNamespaces.size() > 0) { + MessagePacket receipt = mXmppConnectionService.getMessageGenerator().received(account, + packet, + receiptsNamespaces, + packet.getType()); + mXmppConnectionService.sendMessagePacket(account, receipt); + } + } else { + if (request) { + query.pendingReceiptRequests.add(new ReceiptRequest(packet.getFrom(), packet.getId())); + } } } diff --git a/src/main/java/de/pixart/messenger/services/MessageArchiveService.java b/src/main/java/de/pixart/messenger/services/MessageArchiveService.java index a7fd66515..277ede64d 100644 --- a/src/main/java/de/pixart/messenger/services/MessageArchiveService.java +++ b/src/main/java/de/pixart/messenger/services/MessageArchiveService.java @@ -12,6 +12,7 @@ import de.pixart.messenger.Config; import de.pixart.messenger.R; import de.pixart.messenger.entities.Account; import de.pixart.messenger.entities.Conversation; +import de.pixart.messenger.entities.ReceiptRequest; import de.pixart.messenger.generator.AbstractGenerator; import de.pixart.messenger.utils.Namespace; import de.pixart.messenger.xml.Element; @@ -278,7 +279,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { if (query.isCatchup() && query.getActualMessageCount() > 0) { mXmppConnectionService.getNotificationService().finishBacklog(true,query.getAccount()); } - query.account.getAxolotlService().processPostponed(); + processPostponed(query); } else { final Query nextQuery; if (query.getPagingOrder() == PagingOrder.NORMAL) { @@ -294,6 +295,17 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { } } + private void processPostponed(Query query) { + query.account.getAxolotlService().processPostponed(); + Log.d(Config.LOGTAG, query.getAccount().getJid().toBareJid() + ": found " + query.pendingReceiptRequests.size() + " pending receipt requests"); + Iterator iterator = query.pendingReceiptRequests.iterator(); + while (iterator.hasNext()) { + ReceiptRequest rr = iterator.next(); + mXmppConnectionService.sendMessagePacket(query.account, mXmppConnectionService.getMessageGenerator().received(query.account, rr.getJid(), rr.getId())); + iterator.remove(); + } + } + public Query findQuery(String id) { if (id == null) { return null; @@ -327,6 +339,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { private PagingOrder pagingOrder = PagingOrder.NORMAL; private XmppConnectionService.OnMoreMessagesLoaded callback = null; private boolean catchup = true; + public HashSet pendingReceiptRequests = new HashSet<>(); public Query(Conversation conversation, MamReference start, long end, boolean catchup) { @@ -352,6 +365,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { query.conversation = conversation; query.totalCount = totalCount; query.actualCount = actualCount; + query.pendingReceiptRequests = pendingReceiptRequests; query.callback = callback; query.catchup = catchup; return query; -- cgit v1.2.3