Add contacts migration

This commit is contained in:
Niels Andriesse 2021-05-24 11:35:05 +10:00
parent 04b62df83c
commit d7afcd07f8
6 changed files with 85 additions and 24 deletions

View File

@ -30,26 +30,25 @@ import androidx.multidex.MultiDexApplication;
import org.conscrypt.Conscrypt; import org.conscrypt.Conscrypt;
import org.session.libsession.avatars.AvatarHelper; import org.session.libsession.avatars.AvatarHelper;
import org.session.libsession.messaging.MessagingModuleConfiguration; import org.session.libsession.messaging.MessagingModuleConfiguration;
import org.session.libsession.messaging.mentions.MentionsManager; import org.session.libsession.messaging.contacts.Contact;
import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier; import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier;
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPollerV2; import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPollerV2;
import org.session.libsession.messaging.sending_receiving.pollers.Poller; import org.session.libsession.messaging.sending_receiving.pollers.Poller;
import org.session.libsession.snode.SnodeModule; import org.session.libsession.snode.SnodeModule;
import org.session.libsession.utilities.Address; import org.session.libsession.utilities.Address;
import org.session.libsession.utilities.IdentityKeyUtil;
import org.session.libsession.utilities.ProfileKeyUtil;
import org.session.libsession.utilities.ProfilePictureUtilities; import org.session.libsession.utilities.ProfilePictureUtilities;
import org.session.libsession.utilities.SSKEnvironment; import org.session.libsession.utilities.SSKEnvironment;
import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.Util; import org.session.libsession.utilities.Util;
import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageContextWrapper; import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageContextWrapper;
import org.session.libsession.utilities.dynamiclanguage.LocaleParser; import org.session.libsession.utilities.dynamiclanguage.LocaleParser;
import org.session.libsignal.database.LokiAPIDatabaseProtocol; import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsignal.utilities.Log; import org.session.libsignal.utilities.Log;
import org.session.libsignal.utilities.ThreadUtils; import org.session.libsignal.utilities.ThreadUtils;
import org.signal.aesgcmprovider.AesGcmProvider; import org.signal.aesgcmprovider.AesGcmProvider;
import org.thoughtcrime.securesms.components.TypingStatusSender; import org.thoughtcrime.securesms.components.TypingStatusSender;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.dependencies.InjectableType; import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule; import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule;
import org.thoughtcrime.securesms.jobmanager.DependencyInjector; import org.thoughtcrime.securesms.jobmanager.DependencyInjector;
@ -65,8 +64,10 @@ import org.thoughtcrime.securesms.loki.api.BackgroundPollWorker;
import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager; import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager;
import org.thoughtcrime.securesms.loki.api.OpenGroupManager; import org.thoughtcrime.securesms.loki.api.OpenGroupManager;
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase; import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase;
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase; import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
import org.thoughtcrime.securesms.loki.utilities.Broadcaster; import org.thoughtcrime.securesms.loki.utilities.Broadcaster;
import org.thoughtcrime.securesms.loki.utilities.ContactUtilities;
import org.thoughtcrime.securesms.loki.utilities.FcmUtils; import org.thoughtcrime.securesms.loki.utilities.FcmUtils;
import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities; import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities;
import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier; import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier;
@ -84,14 +85,12 @@ import org.webrtc.PeerConnectionFactory;
import org.webrtc.PeerConnectionFactory.InitializationOptions; import org.webrtc.PeerConnectionFactory.InitializationOptions;
import org.webrtc.voiceengine.WebRtcAudioManager; import org.webrtc.voiceengine.WebRtcAudioManager;
import org.webrtc.voiceengine.WebRtcAudioUtils; import org.webrtc.voiceengine.WebRtcAudioUtils;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.InputStream; import java.io.InputStream;
import java.security.Security; import java.security.Security;
import java.util.Date; import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import dagger.ObjectGraph; import dagger.ObjectGraph;
import kotlin.Unit; import kotlin.Unit;
import kotlinx.coroutines.Job; import kotlinx.coroutines.Job;
@ -152,8 +151,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
initializeDependencyInjection(); initializeDependencyInjection();
NotificationChannels.create(this); NotificationChannels.create(this);
ProcessLifecycleOwner.get().getLifecycle().addObserver(this); ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
// Loki
// ========
AppContext.INSTANCE.configureKovenant(); AppContext.INSTANCE.configureKovenant();
messageNotifier = new OptimizedMessageNotifier(new DefaultMessageNotifier()); messageNotifier = new OptimizedMessageNotifier(new DefaultMessageNotifier());
broadcaster = new Broadcaster(this); broadcaster = new Broadcaster(this);
@ -168,9 +165,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
if (userPublicKey != null) { if (userPublicKey != null) {
registerForFCMIfNeeded(false); registerForFCMIfNeeded(false);
} }
// Set application UI mode (day/night theme) to the user selected one.
UiModeUtilities.setupUiModeToUserSelected(this); UiModeUtilities.setupUiModeToUserSelected(this);
// ========
initializeExpiringMessageManager(); initializeExpiringMessageManager();
initializeTypingStatusRepository(); initializeTypingStatusRepository();
initializeTypingStatusSender(); initializeTypingStatusSender();
@ -188,12 +183,33 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
isAppVisible = true; isAppVisible = true;
Log.i(TAG, "App is now visible."); Log.i(TAG, "App is now visible.");
KeyCachingService.onAppForegrounded(this); KeyCachingService.onAppForegrounded(this);
// Loki
boolean hasPerformedContactMigration = TextSecurePreferences.INSTANCE.hasPerformedContactMigration(this);
if (!hasPerformedContactMigration) {
TextSecurePreferences.INSTANCE.setPerformedContactMigration(this);
Set<Recipient> allContacts = ContactUtilities.getAllContacts(this);
SessionContactDatabase contactDB = DatabaseFactory.getSessionContactDatabase(this);
LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
for (Recipient recipient : allContacts) {
if (recipient.isGroupRecipient()) { continue; }
String sessionID = recipient.getAddress().serialize();
Contact contact = contactDB.getContactWithSessionID(sessionID);
if (contact == null) {
contact = new Contact(sessionID);
String name = userDB.getDisplayName(sessionID);
contact.setName(name);
contact.setProfilePictureURL(recipient.getProfileAvatar());
contact.setProfilePictureEncryptionKey(recipient.getProfileKey());
contact.setTrusted(true);
}
contactDB.setContact(contact);
}
}
if (poller != null) { if (poller != null) {
poller.setCaughtUp(false); poller.setCaughtUp(false);
} }
startPollingIfNeeded(); startPollingIfNeeded();
OpenGroupManager.INSTANCE.setAllCaughtUp(false); OpenGroupManager.INSTANCE.setAllCaughtUp(false);
OpenGroupManager.INSTANCE.startPolling(); OpenGroupManager.INSTANCE.startPolling();
} }
@ -204,7 +220,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
Log.i(TAG, "App is no longer visible."); Log.i(TAG, "App is no longer visible.");
KeyCachingService.onAppBackgrounded(this); KeyCachingService.onAppBackgrounded(this);
messageNotifier.setVisibleThread(-1); messageNotifier.setVisibleThread(-1);
// Loki
if (poller != null) { if (poller != null) {
poller.stopIfNeeded(); poller.stopIfNeeded();
} }

View File

@ -29,6 +29,7 @@ import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase;
import org.thoughtcrime.securesms.loki.database.LokiBackupFilesDatabase; import org.thoughtcrime.securesms.loki.database.LokiBackupFilesDatabase;
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase; import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase; import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
import org.thoughtcrime.securesms.loki.database.SessionJobDatabase; import org.thoughtcrime.securesms.loki.database.SessionJobDatabase;
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase; import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
@ -52,16 +53,13 @@ public class DatabaseFactory {
private final GroupReceiptDatabase groupReceiptDatabase; private final GroupReceiptDatabase groupReceiptDatabase;
private final SearchDatabase searchDatabase; private final SearchDatabase searchDatabase;
private final JobDatabase jobDatabase; private final JobDatabase jobDatabase;
// Loki
private final LokiAPIDatabase lokiAPIDatabase; private final LokiAPIDatabase lokiAPIDatabase;
private final LokiMessageDatabase lokiMessageDatabase; private final LokiMessageDatabase lokiMessageDatabase;
private final LokiThreadDatabase lokiThreadDatabase; private final LokiThreadDatabase lokiThreadDatabase;
private final LokiUserDatabase lokiUserDatabase;
private final LokiBackupFilesDatabase lokiBackupFilesDatabase; private final LokiBackupFilesDatabase lokiBackupFilesDatabase;
private final SessionJobDatabase sessionJobDatabase; private final SessionJobDatabase sessionJobDatabase;
private final SessionContactDatabase sessionContactDatabase; private final SessionContactDatabase sessionContactDatabase;
// Refactor
private final Storage storage; private final Storage storage;
private final DatabaseAttachmentProvider attachmentProvider; private final DatabaseAttachmentProvider attachmentProvider;
@ -143,6 +141,10 @@ public class DatabaseFactory {
return getInstance(context).lokiThreadDatabase; return getInstance(context).lokiThreadDatabase;
} }
public static LokiUserDatabase getLokiUserDatabase(Context context) {
return getInstance(context).lokiUserDatabase;
}
public static LokiBackupFilesDatabase getLokiBackupFilesDatabase(Context context) { public static LokiBackupFilesDatabase getLokiBackupFilesDatabase(Context context) {
return getInstance(context).lokiBackupFilesDatabase; return getInstance(context).lokiBackupFilesDatabase;
} }
@ -194,6 +196,7 @@ public class DatabaseFactory {
this.lokiAPIDatabase = new LokiAPIDatabase(context, databaseHelper); this.lokiAPIDatabase = new LokiAPIDatabase(context, databaseHelper);
this.lokiMessageDatabase = new LokiMessageDatabase(context, databaseHelper); this.lokiMessageDatabase = new LokiMessageDatabase(context, databaseHelper);
this.lokiThreadDatabase = new LokiThreadDatabase(context, databaseHelper); this.lokiThreadDatabase = new LokiThreadDatabase(context, databaseHelper);
this.lokiUserDatabase = new LokiUserDatabase(context, databaseHelper);
this.lokiBackupFilesDatabase = new LokiBackupFilesDatabase(context, databaseHelper); this.lokiBackupFilesDatabase = new LokiBackupFilesDatabase(context, databaseHelper);
this.storage = new Storage(context, databaseHelper); this.storage = new Storage(context, databaseHelper);
this.attachmentProvider = new DatabaseAttachmentProvider(context, databaseHelper); this.attachmentProvider = new DatabaseAttachmentProvider(context, databaseHelper);

View File

@ -27,6 +27,7 @@ import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase;
import org.thoughtcrime.securesms.loki.database.LokiBackupFilesDatabase; import org.thoughtcrime.securesms.loki.database.LokiBackupFilesDatabase;
import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase; import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase; import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
import org.thoughtcrime.securesms.loki.database.SessionContactDatabase; import org.thoughtcrime.securesms.loki.database.SessionContactDatabase;
import org.thoughtcrime.securesms.loki.database.SessionJobDatabase; import org.thoughtcrime.securesms.loki.database.SessionJobDatabase;
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsMigration; import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsMigration;
@ -124,6 +125,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
db.execSQL(LokiMessageDatabase.getCreateErrorMessageTableCommand()); db.execSQL(LokiMessageDatabase.getCreateErrorMessageTableCommand());
db.execSQL(LokiThreadDatabase.getCreateSessionResetTableCommand()); db.execSQL(LokiThreadDatabase.getCreateSessionResetTableCommand());
db.execSQL(LokiThreadDatabase.getCreatePublicChatTableCommand()); db.execSQL(LokiThreadDatabase.getCreatePublicChatTableCommand());
db.execSQL(LokiUserDatabase.getCreateDisplayNameTableCommand());
db.execSQL(LokiBackupFilesDatabase.getCreateTableCommand()); db.execSQL(LokiBackupFilesDatabase.getCreateTableCommand());
db.execSQL(SessionJobDatabase.getCreateSessionJobTableCommand()); db.execSQL(SessionJobDatabase.getCreateSessionJobTableCommand());
db.execSQL(LokiMessageDatabase.getUpdateMessageIDTableForType()); db.execSQL(LokiMessageDatabase.getUpdateMessageIDTableForType());

View File

@ -0,0 +1,40 @@
package org.thoughtcrime.securesms.loki.database
import android.content.Context
import org.thoughtcrime.securesms.database.Database
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
import org.thoughtcrime.securesms.loki.utilities.get
import org.session.libsession.utilities.TextSecurePreferences
class LokiUserDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) {
companion object {
// Shared
private val displayName = "display_name"
// Display name cache
private val displayNameTable = "loki_user_display_name_database"
private val publicKey = "hex_encoded_public_key"
@JvmStatic val createDisplayNameTableCommand = "CREATE TABLE $displayNameTable ($publicKey TEXT PRIMARY KEY, $displayName TEXT);"
// Server display name cache
private val serverDisplayNameTable = "loki_user_server_display_name_database"
private val serverID = "server_id"
@JvmStatic val createServerDisplayNameTableCommand = "CREATE TABLE $serverDisplayNameTable ($publicKey TEXT, $serverID TEXT, $displayName TEXT, PRIMARY KEY ($publicKey, $serverID));"
}
fun getDisplayName(publicKey: String): String? {
if (publicKey == TextSecurePreferences.getLocalNumber(context)) {
return TextSecurePreferences.getProfileName(context)
} else {
val database = databaseHelper.readableDatabase
val result = database.get(displayNameTable, "${Companion.publicKey} = ?", arrayOf( publicKey )) { cursor ->
cursor.getString(cursor.getColumnIndexOrThrow(displayName))
} ?: return null
val suffix = " (...${publicKey.substring(publicKey.count() - 8)})"
if (result.endsWith(suffix)) {
return result.substring(0..(result.count() - suffix.count()))
} else {
return result
}
}
}
}

View File

@ -764,12 +764,12 @@ object TextSecurePreferences {
fun shouldUpdateProfile(context: Context, profileUpdateTime: Long) = fun shouldUpdateProfile(context: Context, profileUpdateTime: Long) =
profileUpdateTime > getLongPreference(context, LAST_PROFILE_UPDATE_TIME, 0) profileUpdateTime > getLongPreference(context, LAST_PROFILE_UPDATE_TIME, 0)
fun hasSeenFileServerInstabilityNotification(context: Context): Boolean { fun hasPerformedContactMigration(context: Context): Boolean {
return getBooleanPreference(context, "has_seen_file_server_instability_notification", false) return getBooleanPreference(context, "has_performed_contact_migration", false)
} }
fun setHasSeenFileServerInstabilityNotification(context: Context) { fun setPerformedContactMigration(context: Context) {
setBooleanPreference(context, "has_seen_file_server_instability_notification", true) setBooleanPreference(context, "has_performed_contact_migration", true)
} }
// endregion // endregion
} }

View File

@ -26,6 +26,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.annimon.stream.function.Consumer; import com.annimon.stream.function.Consumer;
import com.esotericsoftware.kryo.util.Null;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
import org.session.libsession.database.StorageProtocol; import org.session.libsession.database.StorageProtocol;