Prevent group leave event from bumping conversation.

This commit is contained in:
Cody Henthorne
2021-09-16 12:36:00 -04:00
committed by Alex Hart
parent b4465953d8
commit 5e968eb831
20 changed files with 989 additions and 51 deletions

View File

@@ -236,7 +236,9 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns
final int getOutgoingSecureMessageCount(long threadId) {
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
String[] projection = new String[] {"COUNT(*)"};
String query = getOutgoingSecureMessageClause() + "AND " + MmsSmsColumns.THREAD_ID + " = ? AND" + "(" + getTypeField() + " & " + Types.GROUP_QUIT_BIT + " = 0)";
String query = getOutgoingSecureMessageClause() +
"AND " + MmsSmsColumns.THREAD_ID + " = ? " +
"AND (" + getTypeField() + " & " + Types.GROUP_LEAVE_BIT + " = 0 OR " + getTypeField() + " & " + Types.GROUP_V2_BIT + " = " + Types.GROUP_V2_BIT + ")";
String[] args = new String[]{String.valueOf(threadId)};
try (Cursor cursor = db.query(getTableName(), projection, query, args, null, null, null, null)) {

View File

@@ -528,9 +528,9 @@ public class MmsDatabase extends MessageDatabase {
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
String[] columns = new String[]{ID};
String query = ID + " = ? AND " + MESSAGE_BOX + " & ?";
long type = Types.getOutgoingEncryptedMessageType() | Types.GROUP_QUIT_BIT;
String[] args = new String[]{String.valueOf(messageId), String.valueOf(type)};
long type = Types.getOutgoingEncryptedMessageType() | Types.GROUP_LEAVE_BIT;
String query = ID + " = ? AND " + MESSAGE_BOX + " & " + type + " = " + type + " AND " + MESSAGE_BOX + " & " + Types.GROUP_V2_BIT + " = 0";
String[] args = SqlUtil.buildArgs(messageId);
try (Cursor cursor = db.query(TABLE_NAME, columns, query, args, null, null, null, null)) {
if (cursor.getCount() == 1) {
@@ -546,9 +546,9 @@ public class MmsDatabase extends MessageDatabase {
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
String[] columns = new String[]{DATE_SENT};
String query = THREAD_ID + " = ? AND " + MESSAGE_BOX + " & ? AND " + DATE_SENT + " < ?";
long type = Types.getOutgoingEncryptedMessageType() | Types.GROUP_QUIT_BIT;
String[] args = new String[]{String.valueOf(threadId), String.valueOf(type), String.valueOf(quitTimeBarrier)};
long type = Types.getOutgoingEncryptedMessageType() | Types.GROUP_LEAVE_BIT;
String query = THREAD_ID + " = ? AND " + MESSAGE_BOX + " & " + type + " = " + type + " AND " + MESSAGE_BOX + " & " + Types.GROUP_V2_BIT + " = 0 AND " + DATE_SENT + " < ?";
String[] args = new String[]{String.valueOf(threadId), String.valueOf(quitTimeBarrier)};
String orderBy = DATE_SENT + " DESC";
String limit = "1";
@@ -1490,10 +1490,13 @@ public class MmsDatabase extends MessageDatabase {
OutgoingGroupUpdateMessage outgoingGroupUpdateMessage = (OutgoingGroupUpdateMessage) message;
if (outgoingGroupUpdateMessage.isV2Group()) {
type |= Types.GROUP_V2_BIT | Types.GROUP_UPDATE_BIT;
if (outgoingGroupUpdateMessage.isJustAGroupLeave()) {
type |= Types.GROUP_LEAVE_BIT;
}
} else {
MessageGroupContext.GroupV1Properties properties = outgoingGroupUpdateMessage.requireGroupV1Properties();
if (properties.isUpdate()) type |= Types.GROUP_UPDATE_BIT;
else if (properties.isQuit()) type |= Types.GROUP_QUIT_BIT;
else if (properties.isQuit()) type |= Types.GROUP_LEAVE_BIT;
}
}

View File

@@ -118,9 +118,11 @@ public interface MmsSmsColumns {
// Group Message Information
protected static final long GROUP_UPDATE_BIT = 0x10000;
protected static final long GROUP_QUIT_BIT = 0x20000;
// Note: Leave bit was previous QUIT bit for GV1, now also general member leave for GV2
protected static final long GROUP_LEAVE_BIT = 0x20000;
protected static final long EXPIRATION_TIMER_UPDATE_BIT = 0x40000;
protected static final long GROUP_V2_BIT = 0x80000;
protected static final long GROUP_V2_LEAVE_BITS = GROUP_V2_BIT | GROUP_LEAVE_BIT | GROUP_UPDATE_BIT;
// Encrypted Storage Information XXX
public static final long ENCRYPTION_MASK = 0xFF000000;
@@ -303,7 +305,7 @@ public interface MmsSmsColumns {
}
public static boolean isGroupQuit(long type) {
return (type & GROUP_QUIT_BIT) != 0;
return (type & GROUP_LEAVE_BIT) != 0 && (type & GROUP_V2_BIT) == 0;
}
public static boolean isChatSessionRefresh(long type) {
@@ -339,6 +341,10 @@ public interface MmsSmsColumns {
return type == CHANGE_NUMBER_TYPE;
}
public static boolean isGroupV2LeaveOnly(long type) {
return (type & GROUP_V2_LEAVE_BITS) == GROUP_V2_LEAVE_BITS;
}
public static long translateFromSystemBaseType(long theirType) {
// public static final int NONE_TYPE = 0;
// public static final int INBOX_TYPE = 1;

View File

@@ -21,6 +21,7 @@ import android.database.Cursor;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.annimon.stream.Stream;
@@ -47,6 +48,8 @@ import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static org.thoughtcrime.securesms.database.MmsSmsColumns.Types.GROUP_V2_LEAVE_BITS;
public class MmsSmsDatabase extends Database {
@SuppressWarnings("unused")
@@ -107,11 +110,11 @@ public class MmsSmsDatabase extends Database {
MmsSmsColumns.VIEWED_RECEIPT_COUNT,
MmsSmsColumns.RECEIPT_TIMESTAMP};
private static final String SNIPPET_QUERY = "SELECT " + MmsSmsColumns.ID + ", 0 AS " + TRANSPORT + ", " + SmsDatabase.TYPE + " AS " + MmsSmsColumns.NORMALIZED_TYPE + ", " + SmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " FROM " + SmsDatabase.TABLE_NAME + " " +
"WHERE " + MmsSmsColumns.THREAD_ID + " = ? AND " + SmsDatabase.TYPE + " NOT IN (" + SmsDatabase.Types.PROFILE_CHANGE_TYPE + ", " + SmsDatabase.Types.GV1_MIGRATION_TYPE + ", " + SmsDatabase.Types.CHANGE_NUMBER_TYPE + ") " +
private static final String SNIPPET_QUERY = "SELECT " + MmsSmsColumns.ID + ", 0 AS " + TRANSPORT + ", " + SmsDatabase.TYPE + " AS " + MmsSmsColumns.NORMALIZED_TYPE + ", " + SmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " FROM " + SmsDatabase.TABLE_NAME + " " +
"WHERE " + MmsSmsColumns.THREAD_ID + " = ? AND " + SmsDatabase.TYPE + " NOT IN (" + SmsDatabase.Types.PROFILE_CHANGE_TYPE + ", " + SmsDatabase.Types.GV1_MIGRATION_TYPE + ", " + SmsDatabase.Types.CHANGE_NUMBER_TYPE + ") AND " + SmsDatabase.TYPE + " & " + GROUP_V2_LEAVE_BITS + " != " + GROUP_V2_LEAVE_BITS + " " +
"UNION ALL " +
"SELECT " + MmsSmsColumns.ID + ", 1 AS " + TRANSPORT + ", " + MmsDatabase.MESSAGE_BOX + " AS " + MmsSmsColumns.NORMALIZED_TYPE + ", " + MmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " FROM " + MmsDatabase.TABLE_NAME + " " +
"WHERE " + MmsSmsColumns.THREAD_ID + " = ? " +
"WHERE " + MmsSmsColumns.THREAD_ID + " = ? AND " + MmsDatabase.MESSAGE_BOX + " & " + GROUP_V2_LEAVE_BITS + " != " + GROUP_V2_LEAVE_BITS + " " +
"ORDER BY " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " DESC " +
"LIMIT 1";
@@ -220,8 +223,7 @@ public class MmsSmsDatabase extends Database {
}
public @NonNull MessageRecord getConversationSnippet(long threadId) throws NoSuchMessageException {
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
try (Cursor cursor = db.rawQuery(SNIPPET_QUERY, SqlUtil.buildArgs(threadId, threadId))) {
try (Cursor cursor = getConversationSnippetCursor(threadId)) {
if (cursor.moveToFirst()) {
boolean isMms = CursorUtil.requireBoolean(cursor, TRANSPORT);
long id = CursorUtil.requireLong(cursor, MmsSmsColumns.ID);
@@ -237,6 +239,12 @@ public class MmsSmsDatabase extends Database {
}
}
@VisibleForTesting
@NonNull Cursor getConversationSnippetCursor(long threadId) {
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
return db.rawQuery(SNIPPET_QUERY, SqlUtil.buildArgs(threadId, threadId));
}
public long getConversationSnippetType(long threadId) throws NoSuchMessageException {
SQLiteDatabase db = databaseHelper.getSignalReadableDatabase();
try (Cursor cursor = db.rawQuery(SNIPPET_QUERY, SqlUtil.buildArgs(threadId, threadId))) {

View File

@@ -24,6 +24,7 @@ import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.annimon.stream.Stream;
import com.google.android.mms.pdu_alt.NotificationInd;
@@ -77,6 +78,8 @@ import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import static org.thoughtcrime.securesms.database.MmsSmsColumns.Types.GROUP_V2_LEAVE_BITS;
/**
* Database for storage of SMS messages.
*
@@ -150,7 +153,8 @@ public class SmsDatabase extends MessageDatabase {
REMOTE_DELETED, NOTIFIED_TIMESTAMP, RECEIPT_TIMESTAMP
};
private static final long IGNORABLE_TYPESMASK_WHEN_COUNTING = Types.END_SESSION_BIT | Types.KEY_EXCHANGE_IDENTITY_UPDATE_BIT | Types.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT;
@VisibleForTesting
static final long IGNORABLE_TYPESMASK_WHEN_COUNTING = Types.END_SESSION_BIT | Types.KEY_EXCHANGE_IDENTITY_UPDATE_BIT | Types.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT;
private static final EarlyReceiptCache earlyDeliveryReceiptCache = new EarlyReceiptCache("SmsDelivery");
@@ -271,8 +275,8 @@ public class SmsDatabase extends MessageDatabase {
}
private @NonNull SqlUtil.Query buildMeaningfulMessagesQuery(long threadId) {
String query = THREAD_ID + " = ? AND (NOT " + TYPE + " & ? AND TYPE != ? AND TYPE != ?)";
return SqlUtil.buildQuery(query, threadId, IGNORABLE_TYPESMASK_WHEN_COUNTING, Types.PROFILE_CHANGE_TYPE, Types.CHANGE_NUMBER_TYPE);
String query = THREAD_ID + " = ? AND (NOT " + TYPE + " & ? AND " + TYPE + " != ? AND " + TYPE + "!= ? AND NOT " + TYPE + " & ?)";
return SqlUtil.buildQuery(query, threadId, IGNORABLE_TYPESMASK_WHEN_COUNTING, Types.PROFILE_CHANGE_TYPE, Types.CHANGE_NUMBER_TYPE, GROUP_V2_LEAVE_BITS);
}
@Override
@@ -1088,9 +1092,16 @@ public class SmsDatabase extends MessageDatabase {
type |= Types.SECURE_MESSAGE_BIT;
if (incomingGroupUpdateMessage.isGroupV2()) type |= Types.GROUP_V2_BIT | Types.GROUP_UPDATE_BIT;
else if (incomingGroupUpdateMessage.isUpdate()) type |= Types.GROUP_UPDATE_BIT;
else if (incomingGroupUpdateMessage.isQuit()) type |= Types.GROUP_QUIT_BIT;
if (incomingGroupUpdateMessage.isGroupV2()) {
type |= Types.GROUP_V2_BIT | Types.GROUP_UPDATE_BIT;
if (incomingGroupUpdateMessage.isJustAGroupLeave()) {
type |= Types.GROUP_LEAVE_BIT;
}
} else if (incomingGroupUpdateMessage.isUpdate()) {
type |= Types.GROUP_UPDATE_BIT;
} else if (incomingGroupUpdateMessage.isQuit()) {
type |= Types.GROUP_LEAVE_BIT;
}
} else if (message.isEndSession()) {
type |= Types.SECURE_MESSAGE_BIT;

View File

@@ -1515,7 +1515,8 @@ public class ThreadDatabase extends Database {
private boolean isSilentType(long type) {
return MmsSmsColumns.Types.isProfileChange(type) ||
MmsSmsColumns.Types.isGroupV1MigrationEvent(type) ||
MmsSmsColumns.Types.isChangeNumber(type);
MmsSmsColumns.Types.isChangeNumber(type) ||
MmsSmsColumns.Types.isGroupV2LeaveOnly(type);
}
public Reader readerFor(Cursor cursor) {