Refactor ApplicationContext

pull/192/head
nielsandriesse 5 years ago
parent 1eedd38861
commit deb2fff0ae

@ -514,7 +514,7 @@
android:exported="true" android:exported="true"
android:theme="@style/TextSecure.LightNoActionBar" /> android:theme="@style/TextSecure.LightNoActionBar" />
<service <service
android:name="org.thoughtcrime.securesms.service.PushNotificationService" android:name="org.thoughtcrime.securesms.loki.api.PushNotificationService"
android:enabled="true" android:enabled="true"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>

@ -22,7 +22,6 @@ import android.arch.lifecycle.ProcessLifecycleOwner;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.database.ContentObserver;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.os.Handler; import android.os.Handler;
@ -41,12 +40,10 @@ import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
import org.thoughtcrime.securesms.crypto.MasterSecretUtil; import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil; import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseContentProviders;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.dependencies.AxolotlStorageModule; import org.thoughtcrime.securesms.dependencies.AxolotlStorageModule;
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.groups.GroupManager;
import org.thoughtcrime.securesms.jobmanager.DependencyInjector; import org.thoughtcrime.securesms.jobmanager.DependencyInjector;
import org.thoughtcrime.securesms.jobmanager.JobManager; import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer; import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer;
@ -62,15 +59,17 @@ import org.thoughtcrime.securesms.logging.CustomSignalProtocolLogger;
import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.logging.PersistentLogger; import org.thoughtcrime.securesms.logging.PersistentLogger;
import org.thoughtcrime.securesms.logging.UncaughtExceptionLogger; import org.thoughtcrime.securesms.logging.UncaughtExceptionLogger;
import org.thoughtcrime.securesms.loki.api.LokiPublicChatManager;
import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager;
import org.thoughtcrime.securesms.loki.MultiDeviceUtilities;
import org.thoughtcrime.securesms.loki.activities.HomeActivity; import org.thoughtcrime.securesms.loki.activities.HomeActivity;
import org.thoughtcrime.securesms.loki.api.BackgroundOpenGroupPollWorker; import org.thoughtcrime.securesms.loki.api.BackgroundOpenGroupPollWorker;
import org.thoughtcrime.securesms.loki.api.BackgroundPollWorker; import org.thoughtcrime.securesms.loki.api.BackgroundPollWorker;
import org.thoughtcrime.securesms.loki.api.LokiPublicChatManager;
import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager;
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.LokiUserDatabase;
import org.thoughtcrime.securesms.loki.shelved.LokiRSSFeedPoller; import org.thoughtcrime.securesms.loki.protocol.EphemeralMessage;
import org.thoughtcrime.securesms.loki.protocol.LokiSessionResetImplementation;
import org.thoughtcrime.securesms.loki.protocol.PushEphemeralMessageSendJob;
import org.thoughtcrime.securesms.loki.utilities.Broadcaster; import org.thoughtcrime.securesms.loki.utilities.Broadcaster;
import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.notifications.NotificationChannels; import org.thoughtcrime.securesms.notifications.NotificationChannels;
@ -100,12 +99,17 @@ import org.whispersystems.signalservice.loki.api.LokiPoller;
import org.whispersystems.signalservice.loki.api.LokiPushNotificationAcknowledgement; import org.whispersystems.signalservice.loki.api.LokiPushNotificationAcknowledgement;
import org.whispersystems.signalservice.loki.api.LokiSwarmAPI; import org.whispersystems.signalservice.loki.api.LokiSwarmAPI;
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI; import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI;
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChat;
import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatAPI; import org.whispersystems.signalservice.loki.api.opengroups.LokiPublicChatAPI;
import org.whispersystems.signalservice.loki.api.p2p.LokiP2PAPI; import org.whispersystems.signalservice.loki.api.p2p.LokiP2PAPI;
import org.whispersystems.signalservice.loki.api.p2p.LokiP2PAPIDelegate; import org.whispersystems.signalservice.loki.api.p2p.LokiP2PAPIDelegate;
import org.whispersystems.signalservice.loki.api.rssfeeds.LokiRSSFeed;
import org.whispersystems.signalservice.loki.database.LokiAPIDatabaseProtocol; import org.whispersystems.signalservice.loki.database.LokiAPIDatabaseProtocol;
import org.whispersystems.signalservice.loki.protocol.friendrequests.FriendRequestProtocol;
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager;
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol;
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol;
import org.whispersystems.signalservice.loki.protocol.sessionmanagement.SessionManagementProtocol;
import org.whispersystems.signalservice.loki.protocol.sessionmanagement.SessionManagementProtocolDelegate;
import org.whispersystems.signalservice.loki.protocol.syncmessages.SyncMessagesProtocol;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -113,7 +117,6 @@ import java.security.SecureRandom;
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.List;
import java.util.Set; import java.util.Set;
import dagger.ObjectGraph; import dagger.ObjectGraph;
@ -131,7 +134,7 @@ import static nl.komponents.kovenant.android.KovenantAndroid.stopKovenant;
* *
* @author Moxie Marlinspike * @author Moxie Marlinspike
*/ */
public class ApplicationContext extends MultiDexApplication implements DependencyInjector, DefaultLifecycleObserver, LokiP2PAPIDelegate { public class ApplicationContext extends MultiDexApplication implements DependencyInjector, DefaultLifecycleObserver, LokiP2PAPIDelegate, SessionManagementProtocolDelegate {
private static final String TAG = ApplicationContext.class.getSimpleName(); private static final String TAG = ApplicationContext.class.getSimpleName();
private final static int OK_HTTP_CACHE_SIZE = 10 * 1024 * 1024; // 10 MB private final static int OK_HTTP_CACHE_SIZE = 10 * 1024 * 1024; // 10 MB
@ -145,10 +148,8 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
private PersistentLogger persistentLogger; private PersistentLogger persistentLogger;
// Loki // Loki
private LokiPoller lokiPoller = null; public LokiPoller lokiPoller = null;
private LokiRSSFeedPoller lokiNewsFeedPoller = null; public LokiPublicChatManager lokiPublicChatManager = null;
private LokiRSSFeedPoller lokiMessengerUpdatesFeedPoller = null;
private LokiPublicChatManager lokiPublicChatManager = null;
private LokiPublicChatAPI lokiPublicChatAPI = null; private LokiPublicChatAPI lokiPublicChatAPI = null;
public Broadcaster broadcaster = null; public Broadcaster broadcaster = null;
public SignalCommunicationModule communicationModule; public SignalCommunicationModule communicationModule;
@ -163,8 +164,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
Log.i(TAG, "onCreate()"); Log.i(TAG, "onCreate()");
broadcaster = new Broadcaster(this);
checkNeedsDatabaseReset();
startKovenant(); startKovenant();
initializeSecurityProvider(); initializeSecurityProvider();
initializeLogging(); initializeLogging();
@ -183,27 +182,31 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
initializeBlobProvider(); initializeBlobProvider();
NotificationChannels.create(this); NotificationChannels.create(this);
ProcessLifecycleOwner.get().getLifecycle().addObserver(this); ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
// Loki - Set up P2P API if needed // Loki
setUpP2PAPI(); broadcaster = new Broadcaster(this);
// Loki - Set up push notification acknowledgement LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(this);
LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
LokiSessionResetImplementation sessionResetImpl = new LokiSessionResetImplementation(this);
if (userPublicKey != null) {
FriendRequestProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
MentionsManager.Companion.configureIfNeeded(userPublicKey, threadDB, userDB);
SessionMetaProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
MultiDeviceProtocol.Companion.configureIfNeeded(apiDB);
SessionManagementProtocol.Companion.configureIfNeeded(sessionResetImpl, threadDB, this);
SyncMessagesProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
}
setUpP2PAPIIfNeeded();
LokiPushNotificationAcknowledgement.Companion.configureIfNeeded(BuildConfig.DEBUG); LokiPushNotificationAcknowledgement.Companion.configureIfNeeded(BuildConfig.DEBUG);
// Loki - Update device mappings
if (setUpStorageAPIIfNeeded()) { if (setUpStorageAPIIfNeeded()) {
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this); if (userPublicKey != null) {
if (userHexEncodedPublicKey != null) { MultiDeviceUtilities.updateDeviceLinksOnServer(this);
if (TextSecurePreferences.getNeedsIsRevokedSlaveDeviceCheck(this)) {
MultiDeviceUtilities.checkIsRevokedSlaveDevice(this);
} else {
// We always update our current device links onto the server in case we failed to do so upon linking
MultiDeviceUtilities.updateDeviceLinksOnServer(this);
}
} }
} }
// Loki - Resubmit profile picture if needed
resubmitProfilePictureIfNeeded(); resubmitProfilePictureIfNeeded();
// Loki - Set up public chat manager
lokiPublicChatManager = new LokiPublicChatManager(this); lokiPublicChatManager = new LokiPublicChatManager(this);
updatePublicChatProfilePictureIfNeeded(); updateOpenGroupProfilePicturesIfNeeded();
registerForFCMIfNeeded(false); registerForFCMIfNeeded(false);
} }
@ -213,9 +216,8 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
Log.i(TAG, "App is now visible."); Log.i(TAG, "App is now visible.");
executePendingContactSync(); executePendingContactSync();
KeyCachingService.onAppForegrounded(this); KeyCachingService.onAppForegrounded(this);
// Loki - Start polling if needed // Loki
startPollingIfNeeded(); startPollingIfNeeded();
// Loki - Start open group polling if needed
lokiPublicChatManager.startPollersIfNeeded(); lokiPublicChatManager.startPollersIfNeeded();
} }
@ -225,14 +227,14 @@ 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 - Stop polling if needed // Loki
if (lokiPoller != null) { lokiPoller.stopIfNeeded(); } if (lokiPoller != null) { lokiPoller.stopIfNeeded(); }
if (lokiPublicChatManager != null) { lokiPublicChatManager.stopPollers(); } if (lokiPublicChatManager != null) { lokiPublicChatManager.stopPollers(); }
} }
@Override @Override
public void onTerminate() { public void onTerminate() {
stopKovenant(); stopKovenant(); // Loki
super.onTerminate(); super.onTerminate();
} }
@ -267,20 +269,15 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
return persistentLogger; return persistentLogger;
} }
public LokiPublicChatManager getLokiPublicChatManager() { // Loki
return lokiPublicChatManager;
}
public @Nullable LokiPublicChatAPI getLokiPublicChatAPI() { public @Nullable LokiPublicChatAPI getLokiPublicChatAPI() {
if (lokiPublicChatAPI == null && IdentityKeyUtil.hasIdentityKey(this)) { if (lokiPublicChatAPI != null || !IdentityKeyUtil.hasIdentityKey(this)) { return lokiPublicChatAPI; }
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this); String userPublicKey = TextSecurePreferences.getLocalNumber(this);
if (userHexEncodedPublicKey != null) { if (userPublicKey== null) { return lokiPublicChatAPI; }
byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize(); byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize();
LokiAPIDatabase apiDatabase = DatabaseFactory.getLokiAPIDatabase(this); LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
LokiUserDatabase userDatabase = DatabaseFactory.getLokiUserDatabase(this); LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
lokiPublicChatAPI = new LokiPublicChatAPI(userHexEncodedPublicKey, userPrivateKey, apiDatabase, userDatabase); lokiPublicChatAPI = new LokiPublicChatAPI(userPublicKey, userPrivateKey, apiDB, userDB);
}
}
return lokiPublicChatAPI; return lokiPublicChatAPI;
} }
@ -362,8 +359,8 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
RotateSignedPreKeyListener.schedule(this); RotateSignedPreKeyListener.schedule(this);
LocalBackupListener.schedule(this); LocalBackupListener.schedule(this);
RotateSenderCertificateListener.schedule(this); RotateSenderCertificateListener.schedule(this);
BackgroundPollWorker.schedule(this); // Session BackgroundPollWorker.schedule(this); // Loki
BackgroundOpenGroupPollWorker.schedule(this); // Session BackgroundOpenGroupPollWorker.schedule(this); // Loki
if (BuildConfig.PLAY_STORE_DISABLED) { if (BuildConfig.PLAY_STORE_DISABLED) {
UpdateApkRefreshListener.schedule(this); UpdateApkRefreshListener.schedule(this);
@ -441,18 +438,16 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
// region Loki // region Loki
public boolean setUpStorageAPIIfNeeded() { public boolean setUpStorageAPIIfNeeded() {
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this); String userPublicKey = TextSecurePreferences.getLocalNumber(this);
if (userHexEncodedPublicKey != null && IdentityKeyUtil.hasIdentityKey(this)) { if (userPublicKey == null || !IdentityKeyUtil.hasIdentityKey(this)) { return false; }
boolean isDebugMode = BuildConfig.DEBUG; boolean isDebugMode = BuildConfig.DEBUG;
byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize(); byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize();
LokiAPIDatabaseProtocol database = DatabaseFactory.getLokiAPIDatabase(this); LokiAPIDatabaseProtocol apiDB = DatabaseFactory.getLokiAPIDatabase(this);
LokiFileServerAPI.Companion.configure(isDebugMode, userHexEncodedPublicKey, userPrivateKey, database); LokiFileServerAPI.Companion.configure(isDebugMode, userPublicKey, userPrivateKey, apiDB);
return true; return true;
}
return false;
} }
public void setUpP2PAPI() { public void setUpP2PAPIIfNeeded() {
String hexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this); String hexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this);
if (hexEncodedPublicKey == null) { return; } if (hexEncodedPublicKey == null) { return; }
LokiP2PAPI.Companion.configure(hexEncodedPublicKey, (isOnline, contactPublicKey) -> { LokiP2PAPI.Companion.configure(hexEncodedPublicKey, (isOnline, contactPublicKey) -> {
@ -469,10 +464,10 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
return; return;
} }
String token = task.getResult().getToken(); String token = task.getResult().getToken();
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context); String userPublicKey = TextSecurePreferences.getLocalNumber(context);
if (userHexEncodedPublicKey == null) return; if (userPublicKey == null) return;
if (TextSecurePreferences.isUsingFCM(this)) { if (TextSecurePreferences.isUsingFCM(this)) {
LokiPushNotificationManager.register(token, userHexEncodedPublicKey, context, force); LokiPushNotificationManager.register(token, userPublicKey, context, force);
} else { } else {
LokiPushNotificationManager.unregister(token, context); LokiPushNotificationManager.unregister(token, context);
} }
@ -486,13 +481,13 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
private void setUpPollingIfNeeded() { private void setUpPollingIfNeeded() {
if (lokiPoller != null) return; if (lokiPoller != null) return;
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this); String userPublicKey = TextSecurePreferences.getLocalNumber(this);
if (userHexEncodedPublicKey == null) return; if (userPublicKey == null) return;
LokiAPIDatabase lokiAPIDatabase = DatabaseFactory.getLokiAPIDatabase(this); LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
Context context = this; Context context = this;
LokiSwarmAPI.Companion.configureIfNeeded(lokiAPIDatabase); LokiSwarmAPI.Companion.configureIfNeeded(apiDB);
LokiAPI.Companion.configureIfNeeded(userHexEncodedPublicKey, lokiAPIDatabase, broadcaster); LokiAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
lokiPoller = new LokiPoller(userHexEncodedPublicKey, lokiAPIDatabase, protos -> { lokiPoller = new LokiPoller(userPublicKey, apiDB, protos -> {
for (SignalServiceProtos.Envelope proto : protos) { for (SignalServiceProtos.Envelope proto : protos) {
new PushContentReceiveJob(context).processEnvelope(new SignalServiceEnvelope(proto)); new PushContentReceiveJob(context).processEnvelope(new SignalServiceEnvelope(proto));
} }
@ -505,103 +500,9 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
if (lokiPoller != null) { lokiPoller.startIfNeeded(); } if (lokiPoller != null) { lokiPoller.startIfNeeded(); }
} }
private LokiRSSFeed lokiNewsFeed() {
return new LokiRSSFeed("loki.network.feed", "https://loki.network/feed/", "Loki News", true);
}
private LokiRSSFeed lokiMessengerUpdatesFeed() {
return new LokiRSSFeed("loki.network.messenger-updates.feed", "https://loki.network/category/messenger-updates/feed", "Session Updates", false);
}
public void createDefaultPublicChatsIfNeeded() {
List<LokiPublicChat> defaultPublicChats = LokiPublicChatAPI.Companion.getDefaultChats(BuildConfig.DEBUG);
for (LokiPublicChat publicChat : defaultPublicChats) {
long threadID = GroupManager.getOpenGroupThreadID(publicChat.getId(), this);
String migrationKey = publicChat.getId() + "_migrated";
boolean isChatMigrated = TextSecurePreferences.getBooleanPreference(this, migrationKey, false);
boolean isChatSetUp = TextSecurePreferences.isChatSetUp(this, publicChat.getId());
if (!isChatSetUp || !publicChat.isDeletable()) {
lokiPublicChatManager.addChat(publicChat.getServer(), publicChat.getChannel(), publicChat.getDisplayName());
TextSecurePreferences.markChatSetUp(this, publicChat.getId());
TextSecurePreferences.setBooleanPreference(this, migrationKey, true);
} else if (threadID > -1 && !isChatMigrated) {
// Migrate the old public chats
DatabaseFactory.getLokiThreadDatabase(this).setPublicChat(publicChat, threadID);
TextSecurePreferences.setBooleanPreference(this, migrationKey, true);
}
}
}
public void createRSSFeedsIfNeeded() {
return;
/*
ArrayList<LokiRSSFeed> feeds = new ArrayList<>();
feeds.add(lokiNewsFeed());
feeds.add(lokiMessengerUpdatesFeed());
for (LokiRSSFeed feed : feeds) {
boolean isFeedSetUp = TextSecurePreferences.isChatSetUp(this, feed.getId());
if (!isFeedSetUp || !feed.isDeletable()) {
GroupManager.createRSSFeed(feed.getId(), this, null, feed.getDisplayName());
TextSecurePreferences.markChatSetUp(this, feed.getId());
}
}
*/
}
private void createRSSFeedPollersIfNeeded() {
return;
/*
// Only create the RSS feed pollers if their threads aren't deleted
LokiRSSFeed lokiNewsFeed = lokiNewsFeed();
long lokiNewsFeedThreadID = GroupManager.getRSSFeedThreadID(lokiNewsFeed.getId(), this);
if (lokiNewsFeedThreadID >= 0 && lokiNewsFeedPoller == null) {
lokiNewsFeedPoller = new LokiRSSFeedPoller(this, lokiNewsFeed);
// Set up deletion listeners if needed
setUpThreadDeletionListeners(lokiNewsFeedThreadID, () -> {
if (lokiNewsFeedPoller != null) lokiNewsFeedPoller.stop();
lokiNewsFeedPoller = null;
});
}
// The user can't delete the Session Updates RSS feed
if (lokiMessengerUpdatesFeedPoller == null) {
lokiMessengerUpdatesFeedPoller = new LokiRSSFeedPoller(this, lokiMessengerUpdatesFeed());
}
*/
}
private void setUpThreadDeletionListeners(long threadID, Runnable onDelete) {
if (threadID < 0) { return; }
ContentObserver observer = new ContentObserver(null) {
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
// Stop the poller if thread is deleted
try {
if (!DatabaseFactory.getThreadDatabase(getApplicationContext()).hasThread(threadID)) {
onDelete.run();
getContentResolver().unregisterContentObserver(this);
}
} catch (Exception e) {
// TODO: Handle
}
}
};
this.getContentResolver().registerContentObserver(DatabaseContentProviders.Conversation.getUriForThread(threadID), true, observer);
}
public void startRSSFeedPollersIfNeeded() {
return;
/*
createRSSFeedPollersIfNeeded();
if (lokiNewsFeedPoller != null) lokiNewsFeedPoller.startIfNeeded();
if (lokiMessengerUpdatesFeedPoller != null) lokiMessengerUpdatesFeedPoller.startIfNeeded();
*/
}
private void resubmitProfilePictureIfNeeded() { private void resubmitProfilePictureIfNeeded() {
String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this); String userPublicKey = TextSecurePreferences.getLocalNumber(this);
if (userHexEncodedPublicKey == null) return; if (userPublicKey == null) return;
long now = new Date().getTime(); long now = new Date().getTime();
long lastProfilePictureUpload = TextSecurePreferences.getLastProfilePictureUpload(this); long lastProfilePictureUpload = TextSecurePreferences.getLastProfilePictureUpload(this);
if (now - lastProfilePictureUpload <= 14 * 24 * 60 * 60 * 1000) return; if (now - lastProfilePictureUpload <= 14 * 24 * 60 * 60 * 1000) return;
@ -609,7 +510,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
String encodedProfileKey = ProfileKeyUtil.generateEncodedProfileKey(this); String encodedProfileKey = ProfileKeyUtil.generateEncodedProfileKey(this);
byte[] profileKey = ProfileKeyUtil.getProfileKeyFromEncodedString(encodedProfileKey); byte[] profileKey = ProfileKeyUtil.getProfileKeyFromEncodedString(encodedProfileKey);
try { try {
File profilePicture = AvatarHelper.getAvatarFile(this, Address.fromSerialized(userHexEncodedPublicKey)); File profilePicture = AvatarHelper.getAvatarFile(this, Address.fromSerialized(userPublicKey));
StreamDetails stream = new StreamDetails(new FileInputStream(profilePicture), "image/jpeg", profilePicture.length()); StreamDetails stream = new StreamDetails(new FileInputStream(profilePicture), "image/jpeg", profilePicture.length());
LokiFileServerAPI.shared.uploadProfilePicture(LokiFileServerAPI.shared.getServer(), profileKey, stream, () -> { LokiFileServerAPI.shared.uploadProfilePicture(LokiFileServerAPI.shared.getServer(), profileKey, stream, () -> {
TextSecurePreferences.setLastProfilePictureUpload(this, new Date().getTime()); TextSecurePreferences.setLastProfilePictureUpload(this, new Date().getTime());
@ -623,7 +524,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
}); });
} }
public void updatePublicChatProfilePictureIfNeeded() { public void updateOpenGroupProfilePicturesIfNeeded() {
AsyncTask.execute(() -> { AsyncTask.execute(() -> {
LokiPublicChatAPI publicChatAPI = null; LokiPublicChatAPI publicChatAPI = null;
try { try {
@ -631,48 +532,42 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
} catch (Exception e) { } catch (Exception e) {
// Do nothing // Do nothing
} }
if (publicChatAPI != null) { if (publicChatAPI == null) { return; }
byte[] profileKey = ProfileKeyUtil.getProfileKey(this); byte[] profileKey = ProfileKeyUtil.getProfileKey(this);
String url = TextSecurePreferences.getProfilePictureURL(this); String url = TextSecurePreferences.getProfilePictureURL(this);
String ourMasterDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(this); String userMasterDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(this);
if (ourMasterDevice != null) { if (userMasterDevice != null) {
Recipient masterDevice = Recipient.from(this, Address.fromSerialized(ourMasterDevice), false).resolve(); Recipient userMasterDeviceAsRecipient = Recipient.from(this, Address.fromSerialized(userMasterDevice), false).resolve();
profileKey = masterDevice.getProfileKey(); profileKey = userMasterDeviceAsRecipient.getProfileKey();
url = masterDevice.getProfileAvatar(); url = userMasterDeviceAsRecipient.getProfileAvatar();
} }
Set<String> servers = DatabaseFactory.getLokiThreadDatabase(this).getAllPublicChatServers(); Set<String> servers = DatabaseFactory.getLokiThreadDatabase(this).getAllPublicChatServers();
for (String server : servers) { for (String server : servers) {
if (profileKey != null) { if (profileKey != null) {
publicChatAPI.setProfilePicture(server, profileKey, url); publicChatAPI.setProfilePicture(server, profileKey, url);
}
} }
} }
}); });
} }
public void checkNeedsDatabaseReset() {
if (TextSecurePreferences.getNeedsDatabaseReset(this)) {
boolean wasUnlinked = TextSecurePreferences.getWasUnlinked(this);
TextSecurePreferences.clearAll(this);
TextSecurePreferences.setWasUnlinked(this, wasUnlinked); // Loki - Re-set the preference so we can use it in the starting screen to determine whether device was unlinked or not
MasterSecretUtil.clear(this);
if (this.deleteDatabase("signal.db")) {
Log.d("Loki", "Deleted database");
}
}
}
public void clearData() { public void clearData() {
TextSecurePreferences.setNeedsDatabaseReset(this, true); boolean wasUnlinked = TextSecurePreferences.getWasUnlinked(this);
TextSecurePreferences.clearAll(this);
TextSecurePreferences.setWasUnlinked(this, wasUnlinked);
MasterSecretUtil.clear(this);
new Handler().postDelayed(this::restartApplication, 200); new Handler().postDelayed(this::restartApplication, 200);
} }
public void restartApplication() { public void restartApplication() {
Intent intent = new Intent(this, HomeActivity.class); Intent intent = new Intent(this, HomeActivity.class);
ComponentName componentName = intent.getComponent(); startActivity(Intent.makeRestartActivityTask(intent.getComponent()));
Intent mainIntent = Intent.makeRestartActivityTask(componentName);
this.startActivity(mainIntent);
Runtime.getRuntime().exit(0); Runtime.getRuntime().exit(0);
} }
@Override
public void sendSessionRequest(@NotNull String publicKey) {
EphemeralMessage sessionRequest = EphemeralMessage.createSessionRequest(publicKey);
jobManager.add(new PushEphemeralMessageSendJob(sessionRequest));
}
// endregion // endregion
} }

@ -427,7 +427,7 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
ProfileKeyUtil.setEncodedProfileKey(context, newProfileKey); ProfileKeyUtil.setEncodedProfileKey(context, newProfileKey);
// Update profile key on the public chat server // Update profile key on the public chat server
ApplicationContext.getInstance(context).updatePublicChatProfilePictureIfNeeded(); ApplicationContext.getInstance(context).updateOpenGroupProfilePicturesIfNeeded();
} catch (Exception e) { } catch (Exception e) {
Log.d("Loki", "Failed to upload profile photo: " + e); Log.d("Loki", "Failed to upload profile photo: " + e);
return false; return false;

@ -100,7 +100,7 @@ class LandingActivity : BaseActionBarActivity(), LinkDeviceSlaveModeDialogDelega
} }
val application = ApplicationContext.getInstance(this) val application = ApplicationContext.getInstance(this)
application.startPollingIfNeeded() application.startPollingIfNeeded()
application.setUpP2PAPI() application.setUpP2PAPIIfNeeded()
application.setUpStorageAPIIfNeeded() application.setUpStorageAPIIfNeeded()
val linkDeviceDialog = LinkDeviceSlaveModeDialog() val linkDeviceDialog = LinkDeviceSlaveModeDialog()
linkDeviceDialog.delegate = this linkDeviceDialog.delegate = this

@ -91,7 +91,7 @@ class PNModeActivity : BaseActionBarActivity() {
TextSecurePreferences.setHasSeenPNModeSheet(this, true) // Shouldn't be shown to users who've done the new onboarding TextSecurePreferences.setHasSeenPNModeSheet(this, true) // Shouldn't be shown to users who've done the new onboarding
val application = ApplicationContext.getInstance(this) val application = ApplicationContext.getInstance(this)
application.setUpStorageAPIIfNeeded() application.setUpStorageAPIIfNeeded()
application.setUpP2PAPI() application.setUpP2PAPIIfNeeded()
val publicChatAPI = ApplicationContext.getInstance(this).lokiPublicChatAPI val publicChatAPI = ApplicationContext.getInstance(this).lokiPublicChatAPI
if (publicChatAPI != null) { if (publicChatAPI != null) {
// TODO: This won't be necessary anymore when we don't auto-join the Loki Public Chat anymore // TODO: This won't be necessary anymore when we don't auto-join the Loki Public Chat anymore

@ -183,7 +183,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
AvatarHelper.setAvatar(this, Address.fromSerialized(TextSecurePreferences.getLocalNumber(this)), profilePicture) AvatarHelper.setAvatar(this, Address.fromSerialized(TextSecurePreferences.getLocalNumber(this)), profilePicture)
TextSecurePreferences.setProfileAvatarId(this, SecureRandom().nextInt()) TextSecurePreferences.setProfileAvatarId(this, SecureRandom().nextInt())
ProfileKeyUtil.setEncodedProfileKey(this, encodedProfileKey) ProfileKeyUtil.setEncodedProfileKey(this, encodedProfileKey)
ApplicationContext.getInstance(this).updatePublicChatProfilePictureIfNeeded() ApplicationContext.getInstance(this).updateOpenGroupProfilePicturesIfNeeded()
profilePictureView.update() profilePictureView.update()
} }
profilePictureToBeUploaded = null profilePictureToBeUploaded = null

@ -212,7 +212,7 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
val database = DatabaseFactory.getRecipientDatabase(context) val database = DatabaseFactory.getRecipientDatabase(context)
database.setProfileKey(recipient, profileKey) database.setProfileKey(recipient, profileKey)
database.setProfileAvatar(recipient, url) database.setProfileAvatar(recipient, url)
ApplicationContext.getInstance(context).updatePublicChatProfilePictureIfNeeded() ApplicationContext.getInstance(context).updateOpenGroupProfilePicturesIfNeeded()
} }
} }
} }

@ -1,9 +1,8 @@
package org.thoughtcrime.securesms.service package org.thoughtcrime.securesms.loki.api
import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage import com.google.firebase.messaging.RemoteMessage
import org.thoughtcrime.securesms.jobs.PushContentReceiveJob import org.thoughtcrime.securesms.jobs.PushContentReceiveJob
import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager
import org.thoughtcrime.securesms.util.TextSecurePreferences import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.whispersystems.libsignal.logging.Log import org.whispersystems.libsignal.logging.Log
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope

@ -36,7 +36,7 @@ object SessionMetaProtocol {
fun handleProfileKeyUpdateIfNeeded(context: Context, content: SignalServiceContent) { fun handleProfileKeyUpdateIfNeeded(context: Context, content: SignalServiceContent) {
val userMasterPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context) val userMasterPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context)
if (userMasterPublicKey != content.sender) { return } if (userMasterPublicKey != content.sender) { return }
ApplicationContext.getInstance(context).updatePublicChatProfilePictureIfNeeded() ApplicationContext.getInstance(context).updateOpenGroupProfilePicturesIfNeeded()
} }
/** /**

Loading…
Cancel
Save