Merge remote-tracking branch 'loki/dev' into light-theme

This commit is contained in:
Anton Chekulaev 2020-08-25 15:11:51 +10:00
commit b04028f629
16 changed files with 88 additions and 35 deletions

View File

@ -185,8 +185,8 @@ dependencies {
implementation "com.opencsv:opencsv:4.6"
}
def canonicalVersionCode = 70
def canonicalVersionName = "1.4.3"
def canonicalVersionCode = 72
def canonicalVersionName = "1.4.4"
def postFixSize = 10
def abiPostFix = ['armeabi-v7a' : 1,

View File

@ -1853,4 +1853,6 @@
<string name="dialog_seed_disclaimer">*Please note that it is not possible to use the same Session ID on multiple devices simultaneously</string>
<string name="view_reset_secure_session_done_message">Secure session reset done</string>
</resources>

View File

@ -358,7 +358,7 @@ public class ConversationFragment extends Fragment
if (messageRecord.isGroupAction() || messageRecord.isCallLog() ||
messageRecord.isJoined() || messageRecord.isExpirationTimerUpdate() ||
messageRecord.isEndSession() || messageRecord.isIdentityUpdate() ||
messageRecord.isIdentityVerified() || messageRecord.isIdentityDefault() || messageRecord.isLokiSessionRestoreSent())
messageRecord.isIdentityVerified() || messageRecord.isIdentityDefault() || messageRecord.isLokiSessionRestoreSent() || messageRecord.isLokiSessionRestoreDone())
{
actionMessage = true;
}

View File

@ -114,6 +114,7 @@ public class ConversationUpdateItem extends LinearLayout
else if (messageRecord.isIdentityVerified() ||
messageRecord.isIdentityDefault()) setIdentityVerifyUpdate(messageRecord);
else if (messageRecord.isLokiSessionRestoreSent()) setTextMessageRecord(messageRecord);
else if (messageRecord.isLokiSessionRestoreDone()) setTextMessageRecord(messageRecord);
else throw new AssertionError("Neither group nor log nor joined.");
if (batchSelected.contains(messageRecord)) setSelected(true);

View File

@ -84,6 +84,7 @@ public interface MmsSmsColumns {
// Loki
protected static final long ENCRYPTION_LOKI_SESSION_RESTORE_SENT_BIT = 0x01000000;
protected static final long ENCRYPTION_LOKI_SESSION_RESTORE_DONE_BIT = 0x00100000;
public static boolean isDraftMessageType(long type) {
return (type & BASE_TYPE_MASK) == BASE_DRAFT_TYPE;
@ -237,6 +238,10 @@ public interface MmsSmsColumns {
return (type & ENCRYPTION_LOKI_SESSION_RESTORE_SENT_BIT) != 0;
}
public static boolean isLokiSessionRestoreDoneType(long type) {
return (type & ENCRYPTION_LOKI_SESSION_RESTORE_DONE_BIT) != 0;
}
public static boolean isLegacyType(long type) {
return (type & ENCRYPTION_REMOTE_LEGACY_BIT) != 0 ||
(type & ENCRYPTION_REMOTE_BIT) != 0;

View File

@ -255,6 +255,10 @@ public class SmsDatabase extends MessagingDatabase {
updateTypeBitmask(id, Types.ENCRYPTION_MASK, Types.ENCRYPTION_LOKI_SESSION_RESTORE_SENT_BIT);
}
public void markAsLokiSessionRestorationDone(long id) {
updateTypeBitmask(id, Types.ENCRYPTION_MASK, Types.ENCRYPTION_LOKI_SESSION_RESTORE_DONE_BIT);
}
public void markAsLegacyVersion(long id) {
updateTypeBitmask(id, Types.ENCRYPTION_MASK, Types.ENCRYPTION_REMOTE_LEGACY_BIT);
}

View File

@ -107,6 +107,8 @@ public abstract class DisplayRecord {
public boolean isLokiSessionRestoreSent() { return SmsDatabase.Types.isLokiSessionRestoreSentType(type); }
public boolean isLokiSessionRestoreDone() { return SmsDatabase.Types.isLokiSessionRestoreDoneType(type); }
public boolean isGroupUpdate() {
return SmsDatabase.Types.isGroupUpdate(type);
}

View File

@ -180,7 +180,7 @@ public abstract class MessageRecord extends DisplayRecord {
public boolean isUpdate() {
return isGroupAction() || isJoined() || isExpirationTimerUpdate() || isCallLog() ||
isEndSession() || isIdentityUpdate() || isIdentityVerified() || isIdentityDefault() || isLokiSessionRestoreSent();
isEndSession() || isIdentityUpdate() || isIdentityVerified() || isIdentityDefault() || isLokiSessionRestoreSent() || isLokiSessionRestoreDone();
}
public boolean isMediaPending() {

View File

@ -18,9 +18,10 @@
package org.thoughtcrime.securesms.database.model;
import android.content.Context;
import androidx.annotation.NonNull;
import android.text.SpannableString;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.database.MmsSmsColumns;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
@ -82,7 +83,9 @@ public class SmsMessageRecord extends MessageRecord {
} else if (SmsDatabase.Types.isNoRemoteSessionType(type)) {
return emphasisAdded(context.getString(R.string.MessageDisplayHelper_message_encrypted_for_non_existing_session));
} else if (isLokiSessionRestoreSent()) {
return emphasisAdded(context.getString(R.string.MessageRecord_session_restore_sent, recipient.toShortString()));
return emphasisAdded(context.getString(R.string.SmsMessageRecord_secure_session_reset));
} else if (isLokiSessionRestoreDone()) {
return emphasisAdded(context.getString(R.string.view_reset_secure_session_done_message));
} else if (isEndSession() && isOutgoing()) {
return emphasisAdded(context.getString(R.string.SmsMessageRecord_secure_session_reset));
} else if (isEndSession()) {

View File

@ -19,13 +19,14 @@ package org.thoughtcrime.securesms.database.model;
import android.content.Context;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.StyleSpan;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.database.MmsSmsColumns;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.recipients.Recipient;
@ -83,7 +84,9 @@ public class ThreadRecord extends DisplayRecord {
} else if (SmsDatabase.Types.isNoRemoteSessionType(type)) {
return emphasisAdded(context.getString(R.string.MessageDisplayHelper_message_encrypted_for_non_existing_session));
} else if (isLokiSessionRestoreSent()) {
return emphasisAdded(context.getString(R.string.MessageRecord_session_restore_sent, recipient.toShortString()));
return emphasisAdded(context.getString(R.string.SmsMessageRecord_secure_session_reset));
} else if (isLokiSessionRestoreDone()) {
return emphasisAdded(context.getString(R.string.view_reset_secure_session_done_message));
} else if (SmsDatabase.Types.isEndSessionType(type)) {
return emphasisAdded(context.getString(R.string.ThreadRecord_secure_session_reset));
} else if (MmsSmsColumns.Types.isLegacyType(type)) {

View File

@ -550,7 +550,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
{
try {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
Recipient recipient = getMessageMasterDestination(content.getSender());
Recipient recipient = getMessageDestination(content, message);
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(getMessageMasterDestination(content.getSender()).getAddress(),
message.getTimestamp(), -1,
message.getExpiresInSeconds() * 1000L, true,
@ -1073,7 +1073,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
@NonNull Optional<Long> smsMessageId, @NonNull Throwable e)
{
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
if (SessionMetaProtocol.shouldErrorMessageShow(context, timestamp)) {
if (!smsMessageId.isPresent()) {
Optional<InsertResult> insertResult = insertPlaceholder(sender, senderDevice, timestamp);
@ -1084,6 +1084,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
} else {
smsDatabase.markAsDecryptFailed(smsMessageId.get());
}
}
// FIXME: This is a temporary patch for bad mac issues. At least with this people will be able to message again. We have to figure out the root cause of the issue though.
if (e.getCause() != null) {
@ -1100,14 +1101,14 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
}
}
SessionManagementProtocol.triggerSessionRestorationUI(context, sender);
SessionManagementProtocol.triggerSessionRestorationUI(context, sender, timestamp);
}
private void handleNoSessionMessage(@NonNull String sender, int senderDevice, long timestamp,
@NonNull Optional<Long> smsMessageId)
{
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
if (SessionMetaProtocol.shouldErrorMessageShow(context, timestamp)) {
if (!smsMessageId.isPresent()) {
Optional<InsertResult> insertResult = insertPlaceholder(sender, senderDevice, timestamp);
@ -1118,7 +1119,8 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
} else {
smsDatabase.markAsNoSession(smsMessageId.get());
}
SessionManagementProtocol.triggerSessionRestorationUI(context, sender);
}
SessionManagementProtocol.triggerSessionRestorationUI(context, sender, timestamp);
}
private void handleLegacyMessage(@NonNull String sender, int senderDevice, long timestamp,

View File

@ -307,7 +307,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
override fun getSessionRequestSentTimestamp(publicKey: String): Long? {
val database = databaseHelper.readableDatabase
return database.get(sessionRequestSentTimestampTable, "${LokiAPIDatabase.publicKey} = ?", wrap(publicKey)) { cursor ->
cursor.getInt(LokiAPIDatabase.timestamp)
cursor.getLong(LokiAPIDatabase.timestamp)
}?.toLong()
}

View File

@ -12,6 +12,7 @@ import android.view.ViewGroup
import kotlinx.android.synthetic.main.contact_selection_list_fragment.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader
import org.thoughtcrime.securesms.logging.Log
import org.thoughtcrime.securesms.mms.GlideApp
import org.thoughtcrime.securesms.recipients.Recipient
@ -60,6 +61,11 @@ class ContactSelectionListFragment : Fragment(), LoaderManager.LoaderCallbacks<L
return inflater.inflate(R.layout.contact_selection_list_fragment, container, false)
}
override fun onStop() {
super.onStop()
LoaderManager.getInstance(this).destroyLoader(0)
}
fun setQueryFilter(filter: String?) {
cursorFilter = filter
LoaderManager.getInstance(this).restartLoader(0, null, this)
@ -93,7 +99,12 @@ class ContactSelectionListFragment : Fragment(), LoaderManager.LoaderCallbacks<L
}
private fun update(items: List<ContactSelectionListItem>) {
if (activity?.isDestroyed == true) { return }
if (activity?.isDestroyed == true) {
Log.e(ContactSelectionListFragment::class.java.name,
"Received a loader callback after the fragment was detached from the activity.",
IllegalStateException())
return
}
listAdapter.items = items
mainContentContainer.visibility = if (items.isEmpty()) View.GONE else View.VISIBLE
emptyStateContainer.visibility = if (items.isEmpty()) View.VISIBLE else View.GONE

View File

@ -62,7 +62,8 @@ object SessionManagementProtocol {
val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
val sentTimestamp = apiDB.getSessionRequestSentTimestamp(publicKey) ?: 0
val processedTimestamp = apiDB.getSessionRequestProcessedTimestamp(publicKey) ?: 0
return timestamp > sentTimestamp && timestamp > processedTimestamp
val restorationTimestamp = TextSecurePreferences.getRestorationTime(context)
return timestamp > sentTimestamp && timestamp > processedTimestamp && timestamp > restorationTimestamp
}
@JvmStatic
@ -99,10 +100,13 @@ object SessionManagementProtocol {
}
@JvmStatic
fun triggerSessionRestorationUI(context: Context, publicKey: String) {
fun triggerSessionRestorationUI(context: Context, publicKey: String, errorTimestamp: Long) {
val masterDevicePublicKey = MultiDeviceProtocol.shared.getMasterDevice(publicKey) ?: publicKey
val masterDeviceAsRecipient = recipient(context, masterDevicePublicKey)
if (masterDeviceAsRecipient.isGroupRecipient) { return }
if (TextSecurePreferences.getRestorationTime(context) > errorTimestamp) {
return ApplicationContext.getInstance(context).sendSessionRequestIfNeeded(publicKey)
}
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(masterDeviceAsRecipient)
DatabaseFactory.getLokiThreadDatabase(context).addSessionRestoreDevice(threadID, publicKey)
}

View File

@ -30,6 +30,12 @@ object SessionMetaProtocol {
return shouldIgnoreMessage
}
@JvmStatic
fun shouldErrorMessageShow(context: Context, timestamp: Long): Boolean {
val restorationTimestamp = TextSecurePreferences.getRestorationTime(context)
return timestamp > restorationTimestamp
}
@JvmStatic
fun handleProfileUpdateIfNeeded(context: Context, content: SignalServiceContent) {
val rawDisplayName = content.senderDisplayName.orNull() ?: return

View File

@ -2,7 +2,10 @@ package org.thoughtcrime.securesms.loki.protocol
import android.content.Context
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.database.Address
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.sms.OutgoingTextMessage
import org.whispersystems.libsignal.loki.SessionResetProtocol
import org.whispersystems.libsignal.loki.SessionResetStatus
import org.whispersystems.libsignal.protocol.PreKeySignalMessage
@ -22,7 +25,14 @@ class SessionResetImplementation(private val context: Context) : SessionResetPro
val job = NullMessageSendJob(publicKey)
ApplicationContext.getInstance(context).jobManager.add(job)
}
// TODO: Show session reset succeed message
val smsDB = DatabaseFactory.getSmsDatabase(context)
val recipient = Recipient.from(context, Address.fromSerialized(publicKey), false)
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient)
val infoMessage = OutgoingTextMessage(recipient, "", 0, 0)
val infoMessageID = smsDB.insertMessageOutbox(threadID, infoMessage, false, System.currentTimeMillis(), null)
if (infoMessageID > -1) {
smsDB.markAsLokiSessionRestorationDone(infoMessageID)
}
}
override fun validatePreKeySignalMessage(publicKey: String, message: PreKeySignalMessage) {