Session reset handling.

This commit is contained in:
Mikunj 2019-07-22 09:38:12 +10:00
parent e626e09a45
commit 61622fbd3d
9 changed files with 118 additions and 78 deletions

View File

@ -153,7 +153,7 @@ import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.loki.FriendRequestViewDelegate;
import org.thoughtcrime.securesms.loki.LokiThreadFriendRequestDatabaseDelegate;
import org.thoughtcrime.securesms.loki.LokiThreadDatabaseDelegate;
import org.thoughtcrime.securesms.mediasend.Media;
import org.thoughtcrime.securesms.mediasend.MediaSendActivity;
import org.thoughtcrime.securesms.mms.AttachmentManager;
@ -251,7 +251,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
InputPanel.MediaListener,
ComposeText.CursorPositionChangedListener,
ConversationSearchBottomBar.EventListener,
LokiThreadFriendRequestDatabaseDelegate,
LokiThreadDatabaseDelegate,
FriendRequestViewDelegate
{
private static final String TAG = ConversationActivity.class.getSimpleName();
@ -438,7 +438,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
MessageNotifier.setVisibleThread(threadId);
markThreadAsRead();
DatabaseFactory.getLokiThreadFriendRequestDatabase(this).setDelegate(this);
DatabaseFactory.getLokiThreadDatabase(this).setDelegate(this);
updateInputPanel();
Log.i(TAG, "onResume() Finished: " + (System.currentTimeMillis() - getIntent().getLongExtra(TIMING_EXTRA, 0)));
@ -456,7 +456,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
AudioSlidePlayer.stopAll();
EventBus.getDefault().unregister(this);
DatabaseFactory.getLokiThreadFriendRequestDatabase(this).setDelegate(null);
DatabaseFactory.getLokiThreadDatabase(this).setDelegate(null);
}
@Override
@ -2033,7 +2033,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
private void updateInputPanel() {
boolean hasPendingFriendRequest = DatabaseFactory.getLokiThreadFriendRequestDatabase(this).hasPendingFriendRequest(threadId);
boolean hasPendingFriendRequest = DatabaseFactory.getLokiThreadDatabase(this).hasPendingFriendRequest(threadId);
inputPanel.setEnabled(!hasPendingFriendRequest);
int hintID = hasPendingFriendRequest ? R.string.activity_conversation_pending_friend_request_hint : R.string.activity_conversation_default_hint;
inputPanel.setHint(getResources().getString(hintID));
@ -2195,7 +2195,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
// Loki - Send a friend request if we're not yet friends with the user in question
LokiThreadFriendRequestStatus friendRequestStatus = DatabaseFactory.getLokiThreadFriendRequestDatabase(context).getFriendRequestStatus(threadId);
LokiThreadFriendRequestStatus friendRequestStatus = DatabaseFactory.getLokiThreadDatabase(context).getFriendRequestStatus(threadId);
message.isFriendRequest = (friendRequestStatus != LokiThreadFriendRequestStatus.FRIENDS); // Needed for stageOutgoingMessage(...)
Permissions.with(this)
@ -2711,7 +2711,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
// region Loki
@Override
public void acceptFriendRequest(@NotNull MessageRecord friendRequest) {
DatabaseFactory.getLokiThreadFriendRequestDatabase(this).setFriendRequestStatus(this.threadId, LokiThreadFriendRequestStatus.FRIENDS);
DatabaseFactory.getLokiThreadDatabase(this).setFriendRequestStatus(this.threadId, LokiThreadFriendRequestStatus.FRIENDS);
String contactID = DatabaseFactory.getThreadDatabase(this).getRecipientForThreadId(this.threadId).getAddress().toString();
SignalServiceMessageSender messageSender = ApplicationContext.getInstance(this).communicationModule.provideSignalMessageSender();
SignalServiceAddress address = new SignalServiceAddress(contactID);
@ -2726,7 +2726,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override
public void rejectFriendRequest(@NotNull MessageRecord friendRequest) {
DatabaseFactory.getLokiThreadFriendRequestDatabase(this).setFriendRequestStatus(this.threadId, LokiThreadFriendRequestStatus.NONE);
DatabaseFactory.getLokiThreadDatabase(this).setFriendRequestStatus(this.threadId, LokiThreadFriendRequestStatus.NONE);
String contactID = DatabaseFactory.getThreadDatabase(this).getRecipientForThreadId(this.threadId).getAddress().toString();
DatabaseFactory.getLokiPreKeyBundleDatabase(this).removePreKeyBundle(contactID);
}

View File

@ -92,6 +92,11 @@ public class TextSecureSessionStore implements SessionStore {
}
}
public void archiveAllSessions(@NonNull String name) {
SignalProtocolAddress address = new SignalProtocolAddress(name, -1);
archiveSiblingSessions(address);
}
public void archiveAllSessions() {
synchronized (FILE_LOCK) {
List<SessionDatabase.SessionRow> sessions = DatabaseFactory.getSessionDatabase(context).getAll();

View File

@ -35,7 +35,7 @@ import org.thoughtcrime.securesms.loki.LokiAPIDatabase;
import org.thoughtcrime.securesms.loki.LokiPreKeyRecordDatabase;
import org.thoughtcrime.securesms.loki.LokiPreKeyBundleDatabase;
import org.thoughtcrime.securesms.loki.LokiMessageFriendRequestDatabase;
import org.thoughtcrime.securesms.loki.LokiThreadFriendRequestDatabase;
import org.thoughtcrime.securesms.loki.LokiThreadDatabase;
import org.thoughtcrime.securesms.loki.LokiUserDisplayNameDatabase;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
@ -70,7 +70,7 @@ public class DatabaseFactory {
private final LokiPreKeyRecordDatabase lokiContactPreKeyDatabase;
private final LokiPreKeyBundleDatabase lokiPreKeyBundleDatabase;
private final LokiMessageFriendRequestDatabase lokiMessageFriendRequestDatabase;
private final LokiThreadFriendRequestDatabase lokiThreadFriendRequestDatabase;
private final LokiThreadDatabase lokiThreadDatabase;
private final LokiUserDisplayNameDatabase lokiUserDisplayNameDatabase;
public static DatabaseFactory getInstance(Context context) {
@ -175,8 +175,8 @@ public class DatabaseFactory {
return getInstance(context).lokiMessageFriendRequestDatabase;
}
public static LokiThreadFriendRequestDatabase getLokiThreadFriendRequestDatabase(Context context) {
return getInstance(context).lokiThreadFriendRequestDatabase;
public static LokiThreadDatabase getLokiThreadDatabase(Context context) {
return getInstance(context).lokiThreadDatabase;
}
public static LokiUserDisplayNameDatabase getLokiUserDisplayNameDatabase(Context context) {
@ -219,7 +219,7 @@ public class DatabaseFactory {
this.lokiContactPreKeyDatabase = new LokiPreKeyRecordDatabase(context, databaseHelper);
this.lokiPreKeyBundleDatabase = new LokiPreKeyBundleDatabase(context, databaseHelper);
this.lokiMessageFriendRequestDatabase = new LokiMessageFriendRequestDatabase(context, databaseHelper);
this.lokiThreadFriendRequestDatabase = new LokiThreadFriendRequestDatabase(context, databaseHelper);
this.lokiThreadDatabase = new LokiThreadDatabase(context, databaseHelper);
this.lokiUserDisplayNameDatabase = new LokiUserDisplayNameDatabase(context, databaseHelper);
}

View File

@ -38,7 +38,7 @@ import org.thoughtcrime.securesms.loki.LokiAPIDatabase;
import org.thoughtcrime.securesms.loki.LokiPreKeyRecordDatabase;
import org.thoughtcrime.securesms.loki.LokiMessageFriendRequestDatabase;
import org.thoughtcrime.securesms.loki.LokiPreKeyBundleDatabase;
import org.thoughtcrime.securesms.loki.LokiThreadFriendRequestDatabase;
import org.thoughtcrime.securesms.loki.LokiThreadDatabase;
import org.thoughtcrime.securesms.loki.LokiUserDisplayNameDatabase;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.service.KeyCachingService;
@ -123,7 +123,8 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
db.execSQL(LokiPreKeyBundleDatabase.getCreateTableCommand());
db.execSQL(LokiPreKeyRecordDatabase.getCreateTableCommand());
db.execSQL(LokiMessageFriendRequestDatabase.getCreateTableCommand());
db.execSQL(LokiThreadFriendRequestDatabase.getCreateTableCommand());
db.execSQL(LokiThreadDatabase.getCreateFriendRequestTableCommand());
db.execSQL(LokiThreadDatabase.getCreateSessionResetTableCommand());
db.execSQL(LokiUserDisplayNameDatabase.getCreateTableCommand());
executeStatements(db, SmsDatabase.CREATE_INDEXS);

View File

@ -138,7 +138,7 @@ public class SignalCommunicationModule {
Optional.of(new SecurityEventListener(context)),
TextSecurePreferences.getLocalNumber(context),
DatabaseFactory.getLokiAPIDatabase(context),
DatabaseFactory.getLokiThreadFriendRequestDatabase(context),
DatabaseFactory.getLokiThreadDatabase(context),
DatabaseFactory.getLokiMessageFriendRequestDatabase(context),
DatabaseFactory.getLokiPreKeyBundleDatabase(context));
} else {

View File

@ -64,7 +64,7 @@ import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.loki.LokiMessageFriendRequestDatabase;
import org.thoughtcrime.securesms.loki.LokiPreKeyBundleDatabase;
import org.thoughtcrime.securesms.loki.LokiThreadFriendRequestDatabase;
import org.thoughtcrime.securesms.loki.LokiThreadDatabase;
import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage;
@ -115,6 +115,7 @@ import org.whispersystems.signalservice.loki.crypto.LokiServiceCipher;
import org.whispersystems.signalservice.loki.messaging.LokiMessageFriendRequestStatus;
import org.whispersystems.signalservice.loki.messaging.LokiServiceMessage;
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus;
import org.whispersystems.signalservice.loki.messaging.LokiThreadSessionResetState;
import java.security.MessageDigest;
import java.util.ArrayList;
@ -466,8 +467,15 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
}
if (threadId != null) {
SessionStore sessionStore = new TextSecureSessionStore(context);
sessionStore.deleteAllSessions(content.getSender());
TextSecureSessionStore sessionStore = new TextSecureSessionStore(context);
LokiThreadDatabase lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context);
// sessionStore.deleteAllSessions(content.getSender());
sessionStore.archiveAllSessions(content.getSender());
lokiThreadDatabase.setSessionResetState(threadId, LokiThreadSessionResetState.REQUEST_RECEIVED);
// TODO: Send a background message here
Log.d("LOKI", "Session reset received from " + content.getSender());
SecurityEvent.broadcastSecurityUpdateEvent(context);
MessageNotifier.updateNotification(context, threadId);
@ -832,9 +840,9 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
private void handleFriendRequestIfNeeded(@NonNull SignalServiceEnvelope envelope, @NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message) {
Recipient contactID = getMessageDestination(content, message);
LokiThreadFriendRequestDatabase threadFriendRequestDatabase = DatabaseFactory.getLokiThreadFriendRequestDatabase(context);
LokiThreadDatabase lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context);
long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(contactID);
LokiThreadFriendRequestStatus threadFriendRequestStatus = threadFriendRequestDatabase.getFriendRequestStatus(threadID);
LokiThreadFriendRequestStatus threadFriendRequestStatus = lokiThreadDatabase.getFriendRequestStatus(threadID);
SmsDatabase messageDatabase = DatabaseFactory.getSmsDatabase(context);
LokiMessageFriendRequestDatabase messageFriendRequestDatabase = DatabaseFactory.getLokiMessageFriendRequestDatabase(context);
int messageCount = messageDatabase.getMessageCountForThread(threadID);
@ -850,7 +858,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
// before updating Alice's thread's friend request status to `FRIENDS`,
// we can end up in a deadlock where both users' threads' friend request statuses are
// `REQUEST_SENT`.
threadFriendRequestDatabase.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS);
lokiThreadDatabase.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS);
long messageID = messageDatabase.getIDForMessageAtIndex(threadID, messageCount - 2); // The message before the one that was just received
messageFriendRequestDatabase.setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED);
// Accept the friend request
@ -861,14 +869,14 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
// friend request status is reset to `NONE`. Bob now sends Alice a friend
// request. Alice's thread's friend request status is reset to
// `REQUEST_RECEIVED`.
threadFriendRequestDatabase.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.REQUEST_RECEIVED);
lokiThreadDatabase.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.REQUEST_RECEIVED);
long messageID = messageDatabase.getIDForMessageAtIndex(threadID, messageCount - 1); // The message that was just received
messageFriendRequestDatabase.setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_PENDING);
}
} else if (threadFriendRequestStatus != LokiThreadFriendRequestStatus.FRIENDS) {
// If the thread's friend request status is not `FRIENDS`, but we're receiving a message,
// it must be a friend request accepted message. Declining a friend request doesn't send a message.
threadFriendRequestDatabase.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS);
lokiThreadDatabase.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS);
long messageID = messageDatabase.getIDForMessageAtIndex(threadID, messageCount - 2); // The message before the one that was just received
messageFriendRequestDatabase.setFriendRequestStatus(messageID, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED);
// TODO: Send p2p details here

View File

@ -0,0 +1,79 @@
package org.thoughtcrime.securesms.loki
import android.content.ContentValues
import android.content.Context
import org.thoughtcrime.securesms.database.Database
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.whispersystems.signalservice.loki.messaging.LokiThreadDatabaseProtocol
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus
import org.whispersystems.signalservice.loki.messaging.LokiThreadSessionResetState
class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiThreadDatabaseProtocol {
var delegate: LokiThreadDatabaseDelegate? = null
companion object {
private val sessionResetTableName = "loki_thread_session_reset_database"
private val friendRequestTableName = "loki_thread_friend_request_database"
private val threadID = "thread_id"
private val friendRequestStatus = "friend_request_status"
private val sessionResetState = "session_reset_state"
@JvmStatic val createFriendRequestTableCommand = "CREATE TABLE $friendRequestTableName ($threadID INTEGER PRIMARY KEY, $friendRequestStatus INTEGER DEFAULT 0);"
@JvmStatic val createSessionResetTableCommand = "CREATE TABLE $sessionResetTableName ($threadID INTEGER PRIMARY KEY, $sessionResetState INTEGER DEFAULT 0);"
}
override fun getThreadID(messageID: Long): Long {
return DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageID)
}
fun getFriendRequestStatus(threadID: Long): LokiThreadFriendRequestStatus {
val database = databaseHelper.readableDatabase
val result = database.get(friendRequestTableName, "${Companion.threadID} = ?", arrayOf( threadID.toString() )) { cursor ->
cursor.getInt(friendRequestStatus)
}
return if (result != null) {
LokiThreadFriendRequestStatus.values().first { it.rawValue == result }
} else {
LokiThreadFriendRequestStatus.NONE
}
}
override fun setFriendRequestStatus(threadID: Long, friendRequestStatus: LokiThreadFriendRequestStatus) {
val database = databaseHelper.writableDatabase
val contentValues = ContentValues(2)
contentValues.put(Companion.threadID, threadID)
contentValues.put(Companion.friendRequestStatus, friendRequestStatus.rawValue)
database.insertOrUpdate(friendRequestTableName, contentValues, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
notifyConversationListListeners()
notifyConversationListeners(threadID)
delegate?.handleThreadFriendRequestStatusChanged(threadID)
}
fun hasPendingFriendRequest(threadID: Long): Boolean {
val friendRequestStatus = getFriendRequestStatus(threadID)
return friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENDING || friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENT
|| friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_RECEIVED
}
override fun getSessionResetState(threadID: Long): LokiThreadSessionResetState {
val database = databaseHelper.readableDatabase
val result = database.get(sessionResetTableName, "${Companion.threadID} = ?", arrayOf( threadID.toString() )) { cursor ->
cursor.getInt(sessionResetState)
}
return if (result != null) {
LokiThreadSessionResetState.values().first { it.rawValue == result }
} else {
LokiThreadSessionResetState.NONE
}
}
override fun setSessionResetState(threadID: Long, sessionResetState: LokiThreadSessionResetState) {
val database = databaseHelper.writableDatabase
val contentValues = ContentValues(2)
contentValues.put(Companion.threadID, threadID)
contentValues.put(Companion.sessionResetState, sessionResetState.rawValue)
database.insertOrUpdate(sessionResetTableName, contentValues, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
notifyConversationListListeners()
notifyConversationListeners(threadID)
}
}

View File

@ -1,6 +1,6 @@
package org.thoughtcrime.securesms.loki
interface LokiThreadFriendRequestDatabaseDelegate {
interface LokiThreadDatabaseDelegate {
fun handleThreadFriendRequestStatusChanged(threadID: Long)
}

View File

@ -1,53 +0,0 @@
package org.thoughtcrime.securesms.loki
import android.content.ContentValues
import android.content.Context
import org.thoughtcrime.securesms.database.Database
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.whispersystems.signalservice.loki.messaging.LokiThreadDatabaseProtocol
import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestStatus
class LokiThreadFriendRequestDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiThreadDatabaseProtocol {
var delegate: LokiThreadFriendRequestDatabaseDelegate? = null
companion object {
private val tableName = "loki_thread_friend_request_database"
private val threadID = "thread_id"
private val friendRequestStatus = "friend_request_status"
@JvmStatic val createTableCommand = "CREATE TABLE $tableName ($threadID INTEGER PRIMARY KEY, $friendRequestStatus INTEGER DEFAULT 0);"
}
override fun getThreadID(messageID: Long): Long {
return DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageID)
}
fun getFriendRequestStatus(threadID: Long): LokiThreadFriendRequestStatus {
val database = databaseHelper.readableDatabase
val result = database.get(tableName, "${Companion.threadID} = ?", arrayOf( threadID.toString() )) { cursor ->
cursor.getInt(friendRequestStatus)
}
return if (result != null) {
LokiThreadFriendRequestStatus.values().first { it.rawValue == result }
} else {
LokiThreadFriendRequestStatus.NONE
}
}
override fun setFriendRequestStatus(threadID: Long, friendRequestStatus: LokiThreadFriendRequestStatus) {
val database = databaseHelper.writableDatabase
val contentValues = ContentValues(2)
contentValues.put(Companion.threadID, threadID)
contentValues.put(Companion.friendRequestStatus, friendRequestStatus.rawValue)
database.insertOrUpdate(tableName, contentValues, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
notifyConversationListListeners()
notifyConversationListeners(threadID)
delegate?.handleThreadFriendRequestStatusChanged(threadID)
}
fun hasPendingFriendRequest(threadID: Long): Boolean {
val friendRequestStatus = getFriendRequestStatus(threadID)
return friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENDING || friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENT
|| friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_RECEIVED
}
}