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.session.libsession.avatars.AvatarHelper;
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.pollers.ClosedGroupPollerV2;
import org.session.libsession.messaging.sending_receiving.pollers.Poller;
import org.session.libsession.snode.SnodeModule;
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.SSKEnvironment;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.Util;
import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageContextWrapper;
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.ThreadUtils;
import org.signal.aesgcmprovider.AesGcmProvider;
import org.thoughtcrime.securesms.components.TypingStatusSender;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule;
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.OpenGroupManager;
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.ContactUtilities;
import org.thoughtcrime.securesms.loki.utilities.FcmUtils;
import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities;
import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier;
@ -84,14 +85,12 @@ import org.webrtc.PeerConnectionFactory;
import org.webrtc.PeerConnectionFactory.InitializationOptions;
import org.webrtc.voiceengine.WebRtcAudioManager;
import org.webrtc.voiceengine.WebRtcAudioUtils;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.security.Security;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import dagger.ObjectGraph;
import kotlin.Unit;
import kotlinx.coroutines.Job;
@ -152,8 +151,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
initializeDependencyInjection();
NotificationChannels.create(this);
ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
// Loki
// ========
AppContext.INSTANCE.configureKovenant();
messageNotifier = new OptimizedMessageNotifier(new DefaultMessageNotifier());
broadcaster = new Broadcaster(this);
@ -161,16 +158,14 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
MessagingModuleConfiguration.Companion.configure(this,
DatabaseFactory.getStorage(this),
DatabaseFactory.getAttachmentProvider(this));
DatabaseFactory.getStorage(this),
DatabaseFactory.getAttachmentProvider(this));
SnodeModule.Companion.configure(apiDB, broadcaster);
resubmitProfilePictureIfNeeded();
if (userPublicKey != null) {
registerForFCMIfNeeded(false);
}
// Set application UI mode (day/night theme) to the user selected one.
UiModeUtilities.setupUiModeToUserSelected(this);
// ========
initializeExpiringMessageManager();
initializeTypingStatusRepository();
initializeTypingStatusSender();
@ -188,12 +183,33 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
isAppVisible = true;
Log.i(TAG, "App is now visible.");
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) {
poller.setCaughtUp(false);
}
startPollingIfNeeded();
OpenGroupManager.INSTANCE.setAllCaughtUp(false);
OpenGroupManager.INSTANCE.startPolling();
}
@ -204,7 +220,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
Log.i(TAG, "App is no longer visible.");
KeyCachingService.onAppBackgrounded(this);
messageNotifier.setVisibleThread(-1);
// Loki
if (poller != null) {
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.LokiMessageDatabase;
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.SessionContactDatabase;
@ -52,16 +53,13 @@ public class DatabaseFactory {
private final GroupReceiptDatabase groupReceiptDatabase;
private final SearchDatabase searchDatabase;
private final JobDatabase jobDatabase;
// Loki
private final LokiAPIDatabase lokiAPIDatabase;
private final LokiMessageDatabase lokiMessageDatabase;
private final LokiThreadDatabase lokiThreadDatabase;
private final LokiUserDatabase lokiUserDatabase;
private final LokiBackupFilesDatabase lokiBackupFilesDatabase;
private final SessionJobDatabase sessionJobDatabase;
private final SessionContactDatabase sessionContactDatabase;
// Refactor
private final Storage storage;
private final DatabaseAttachmentProvider attachmentProvider;
@ -143,6 +141,10 @@ public class DatabaseFactory {
return getInstance(context).lokiThreadDatabase;
}
public static LokiUserDatabase getLokiUserDatabase(Context context) {
return getInstance(context).lokiUserDatabase;
}
public static LokiBackupFilesDatabase getLokiBackupFilesDatabase(Context context) {
return getInstance(context).lokiBackupFilesDatabase;
}
@ -194,6 +196,7 @@ public class DatabaseFactory {
this.lokiAPIDatabase = new LokiAPIDatabase(context, databaseHelper);
this.lokiMessageDatabase = new LokiMessageDatabase(context, databaseHelper);
this.lokiThreadDatabase = new LokiThreadDatabase(context, databaseHelper);
this.lokiUserDatabase = new LokiUserDatabase(context, databaseHelper);
this.lokiBackupFilesDatabase = new LokiBackupFilesDatabase(context, databaseHelper);
this.storage = new Storage(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.LokiMessageDatabase;
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.SessionJobDatabase;
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsMigration;
@ -124,6 +125,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
db.execSQL(LokiMessageDatabase.getCreateErrorMessageTableCommand());
db.execSQL(LokiThreadDatabase.getCreateSessionResetTableCommand());
db.execSQL(LokiThreadDatabase.getCreatePublicChatTableCommand());
db.execSQL(LokiUserDatabase.getCreateDisplayNameTableCommand());
db.execSQL(LokiBackupFilesDatabase.getCreateTableCommand());
db.execSQL(SessionJobDatabase.getCreateSessionJobTableCommand());
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) =
profileUpdateTime > getLongPreference(context, LAST_PROFILE_UPDATE_TIME, 0)
fun hasSeenFileServerInstabilityNotification(context: Context): Boolean {
return getBooleanPreference(context, "has_seen_file_server_instability_notification", false)
fun hasPerformedContactMigration(context: Context): Boolean {
return getBooleanPreference(context, "has_performed_contact_migration", false)
}
fun setHasSeenFileServerInstabilityNotification(context: Context) {
setBooleanPreference(context, "has_seen_file_server_instability_notification", true)
fun setPerformedContactMigration(context: Context) {
setBooleanPreference(context, "has_performed_contact_migration", true)
}
// endregion
}

View file

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