Propagate Loki API related errors

This commit is contained in:
Niels Andriesse 2020-03-05 14:07:42 +11:00
parent eb77b7d56b
commit 652201958a
4 changed files with 72 additions and 8 deletions

View File

@ -23,7 +23,6 @@ import android.content.Context;
import android.database.Cursor;
import android.graphics.drawable.ColorDrawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@ -48,6 +47,7 @@ import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.loaders.MessageDetailsLoader;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
@ -158,10 +158,6 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
private void setActionBarColor(MaterialColor color) {
assert getSupportActionBar() != null;
getSupportActionBar().setBackgroundDrawable(new ColorDrawable(color.toActionBarColor(this)));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// getWindow().setStatusBarColor(color.toStatusBarColor(this));
}
}
@Override
@ -403,6 +399,12 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
boolean isGroupNetworkFailure = messageRecord.isFailed() && !messageRecord.getNetworkFailures().isEmpty();
boolean isIndividualNetworkFailure = messageRecord.isFailed() && !isPushGroup && messageRecord.getIdentityKeyMismatches().isEmpty();
LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(getContext());
String errorMessage = lokiMessageDatabase.getErrorMessage(messageRecord.id);
if (errorMessage != null) {
errorText.setText(errorMessage);
}
if (isGroupNetworkFailure || isIndividualNetworkFailure) {
errorText.setVisibility(View.VISIBLE);
resendButton.setVisibility(View.VISIBLE);

View File

@ -80,8 +80,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
private static final int lokiV4 = 25;
private static final int lokiV5 = 26;
private static final int lokiV6 = 27;
private static final int lokiV7 = 28;
private static final int DATABASE_VERSION = lokiV6; // Loki - onUpgrade(...) must be updated to use Loki version numbers if Signal makes any database changes
private static final int DATABASE_VERSION = lokiV7; // Loki - onUpgrade(...) must be updated to use Loki version numbers if Signal makes any database changes
private static final String DATABASE_NAME = "signal.db";
private final Context context;
@ -141,6 +142,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
db.execSQL(LokiPreKeyRecordDatabase.getCreateTableCommand());
db.execSQL(LokiMessageDatabase.getCreateMessageFriendRequestTableCommand());
db.execSQL(LokiMessageDatabase.getCreateMessageToThreadMappingTableCommand());
db.execSQL(LokiMessageDatabase.getCreateErrorMessageTableCommand());
db.execSQL(LokiThreadDatabase.getCreateFriendRequestTableCommand());
db.execSQL(LokiThreadDatabase.getCreateSessionResetTableCommand());
db.execSQL(LokiThreadDatabase.getCreatePublicChatTableCommand());
@ -570,6 +572,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
db.execSQL("ALTER TABLE groups ADD COLUMN admins TEXT");
}
if (oldVersion < lokiV7) {
db.execSQL(LokiMessageDatabase.getCreateErrorMessageTableCommand());
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();

View File

@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.jobs;
import android.support.annotation.NonNull;
import android.util.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
@ -14,6 +15,7 @@ import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.loki.LokiMessageDatabase;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
@ -25,11 +27,15 @@ import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
import org.whispersystems.signalservice.api.messages.SendMessageResult;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
import org.whispersystems.signalservice.loki.api.LokiAPI;
import org.whispersystems.signalservice.loki.api.LokiDeviceLinkUtilities;
import org.whispersystems.signalservice.loki.api.LokiDotNetAPI;
import org.whispersystems.signalservice.loki.api.LokiSnodeProxy;
import org.whispersystems.signalservice.loki.messaging.LokiSyncMessage;
import org.whispersystems.signalservice.loki.utilities.PromiseUtil;
@ -116,6 +122,8 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
return;
}
LokiMessageDatabase lokiMessageDatabase = DatabaseFactory.getLokiMessageDatabase(context);
try {
log(TAG, "Sending message: " + templateMessageId + (hasSameDestination ? "" : "to another device."));
@ -170,6 +178,21 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
database.markAsSentFailed(record.getId());
database.markAsPush(record.getId());
}
} catch (LokiAPI.Error e) {
Log.d("Loki", "Couldn't send message due to error: " + e.getDescription());
if (messageId < 0) { return; }
lokiMessageDatabase.setErrorMessage(record.getId(), e.getDescription());
database.markAsSentFailed(record.getId());
} catch (LokiDotNetAPI.Error e) {
Log.d("Loki", "Couldn't send message due to error: " + e.getDescription());
if (messageId < 0) { return; }
lokiMessageDatabase.setErrorMessage(record.getId(), e.getDescription());
database.markAsSentFailed(record.getId());
} catch (LokiSnodeProxy.Error e) {
Log.d("Loki", "Couldn't send message due to error: " + e.getDescription());
if (messageId < 0) { return; }
lokiMessageDatabase.setErrorMessage(record.getId(), e.getDescription());
database.markAsSentFailed(record.getId());
}
}
@ -196,7 +219,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
}
private boolean deliver(SmsMessageRecord message)
throws UntrustedIdentityException, InsecureFallbackApprovalException, RetryLaterException
throws UntrustedIdentityException, InsecureFallbackApprovalException, RetryLaterException, LokiAPI.Error, LokiDotNetAPI.Error, LokiSnodeProxy.Error
{
try {
// rotateSenderCertificateIfNecessary();
@ -241,7 +264,21 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
// We also need to use the original message ID and not -1
syncMessage = new LokiSyncMessage(masterAddress, templateMessageId);
}
return messageSender.sendMessage(messageId, address, unidentifiedAccess, textSecureMessage, Optional.fromNullable(syncMessage)).getSuccess().isUnidentified();
SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccess, textSecureMessage, Optional.fromNullable(syncMessage));
if (result.getException() != null) {
Throwable exception = result.getException();
if (exception instanceof LokiAPI.Error) {
throw (LokiAPI.Error) exception;
} else if (exception instanceof LokiDotNetAPI.Error) {
throw (LokiDotNetAPI.Error) exception;
} else if (exception instanceof LokiSnodeProxy.Error) {
throw (LokiSnodeProxy.Error) exception;
} else {
return result.getSuccess().isUnidentified();
}
} else {
return result.getSuccess().isUnidentified();
}
}
} catch (UnregisteredUserException e) {
warn(TAG, "Failure", e);

View File

@ -8,6 +8,7 @@ import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.thoughtcrime.securesms.loki.redesign.utilities.get
import org.thoughtcrime.securesms.loki.redesign.utilities.getInt
import org.thoughtcrime.securesms.loki.redesign.utilities.getString
import org.thoughtcrime.securesms.loki.redesign.utilities.insertOrUpdate
import org.whispersystems.signalservice.loki.messaging.LokiMessageDatabaseProtocol
import org.whispersystems.signalservice.loki.messaging.LokiMessageFriendRequestStatus
@ -17,12 +18,15 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
companion object {
private val messageFriendRequestTableName = "loki_message_friend_request_database"
private val messageThreadMappingTableName = "loki_message_thread_mapping_database"
private val errorMessageTableName = "loki_error_message_database"
private val messageID = "message_id"
private val serverID = "server_id"
private val friendRequestStatus = "friend_request_status"
private val threadID = "thread_id"
private val errorMessage = "error_message"
@JvmStatic val createMessageFriendRequestTableCommand = "CREATE TABLE $messageFriendRequestTableName ($messageID INTEGER PRIMARY KEY, $serverID INTEGER DEFAULT 0, $friendRequestStatus INTEGER DEFAULT 0);"
@JvmStatic val createMessageToThreadMappingTableCommand = "CREATE TABLE IF NOT EXISTS $messageThreadMappingTableName ($messageID INTEGER PRIMARY KEY, $threadID INTEGER);"
@JvmStatic val createErrorMessageTableCommand = "CREATE TABLE IF NOT EXISTS $errorMessageTableName ($messageID INTEGER PRIMARY KEY, $errorMessage STRING);"
}
override fun getQuoteServerID(quoteID: Long, quoteeHexEncodedPublicKey: String): Long? {
@ -92,4 +96,19 @@ class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Datab
fun isFriendRequest(messageID: Long): Boolean {
return getFriendRequestStatus(messageID) != LokiMessageFriendRequestStatus.NONE
}
fun getErrorMessage(messageID: Long): String? {
val database = databaseHelper.readableDatabase
return database.get(errorMessageTableName, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
cursor.getString(errorMessage)
}
}
fun setErrorMessage(messageID: Long, errorMessage: String) {
val database = databaseHelper.writableDatabase
val contentValues = ContentValues(2)
contentValues.put(Companion.messageID, messageID)
contentValues.put(Companion.errorMessage, errorMessage)
database.insertOrUpdate(errorMessageTableName, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
}
}