diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index 78dad49b64..4e141431f8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -29,27 +29,32 @@ import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.ProcessLifecycleOwner; import androidx.multidex.MultiDexApplication; -import com.google.firebase.iid.FirebaseInstanceId; - import org.conscrypt.Conscrypt; import org.session.libsession.messaging.MessagingConfiguration; import org.session.libsession.messaging.avatars.AvatarHelper; -import org.session.libsession.utilities.SSKEnvironment; import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier; -import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageContextWrapper; +import org.session.libsession.messaging.threads.Address; +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.libsession.utilities.preferences.ProfileKeyUtil; +import org.session.libsignal.service.api.messages.SignalServiceEnvelope; +import org.session.libsignal.service.api.util.StreamDetails; +import org.session.libsignal.service.internal.push.SignalServiceProtos; +import org.session.libsignal.service.loki.api.Poller; +import org.session.libsignal.service.loki.api.PushNotificationAPI; +import org.session.libsignal.service.loki.api.SnodeAPI; +import org.session.libsignal.service.loki.api.SwarmAPI; +import org.session.libsignal.service.loki.api.fileserver.FileServerAPI; +import org.session.libsignal.service.loki.api.opengroups.PublicChatAPI; +import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol; +import org.session.libsignal.service.loki.utilities.mentions.MentionsManager; +import org.session.libsignal.utilities.logging.Log; import org.signal.aesgcmprovider.AesGcmProvider; -import org.thoughtcrime.securesms.loki.api.SessionProtocolImpl; -import org.thoughtcrime.securesms.sskenvironment.ProfileManager; -import org.thoughtcrime.securesms.sskenvironment.ReadReceiptManager; -import org.thoughtcrime.securesms.sskenvironment.TypingStatusRepository; import org.thoughtcrime.securesms.components.TypingStatusSender; import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; -import org.session.libsession.utilities.preferences.ProfileKeyUtil; -import org.session.libsession.messaging.threads.Address; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.dependencies.InjectableType; @@ -61,7 +66,6 @@ import org.thoughtcrime.securesms.jobs.FastJobStorage; import org.thoughtcrime.securesms.jobs.JobManagerFactories; import org.thoughtcrime.securesms.jobs.PushContentReceiveJob; import org.thoughtcrime.securesms.logging.AndroidLogger; -import org.session.libsignal.utilities.logging.Log; import org.thoughtcrime.securesms.logging.PersistentLogger; import org.thoughtcrime.securesms.logging.UncaughtExceptionLogger; import org.thoughtcrime.securesms.loki.activities.HomeActivity; @@ -69,11 +73,13 @@ import org.thoughtcrime.securesms.loki.api.BackgroundPollWorker; import org.thoughtcrime.securesms.loki.api.ClosedGroupPoller; import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager; import org.thoughtcrime.securesms.loki.api.PublicChatManager; +import org.thoughtcrime.securesms.loki.api.SessionProtocolImpl; 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.protocol.MultiDeviceProtocol; import org.thoughtcrime.securesms.loki.utilities.Broadcaster; +import org.thoughtcrime.securesms.loki.utilities.FcmUtils; import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities; import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier; import org.thoughtcrime.securesms.notifications.NotificationChannels; @@ -83,22 +89,14 @@ import org.thoughtcrime.securesms.service.ExpiringMessageManager; import org.thoughtcrime.securesms.service.KeyCachingService; import org.thoughtcrime.securesms.service.LocalBackupListener; import org.thoughtcrime.securesms.service.UpdateApkRefreshListener; +import org.thoughtcrime.securesms.sskenvironment.ProfileManager; +import org.thoughtcrime.securesms.sskenvironment.ReadReceiptManager; +import org.thoughtcrime.securesms.sskenvironment.TypingStatusRepository; import org.thoughtcrime.securesms.util.dynamiclanguage.LocaleParseHelper; import org.webrtc.PeerConnectionFactory; import org.webrtc.PeerConnectionFactory.InitializationOptions; import org.webrtc.voiceengine.WebRtcAudioManager; import org.webrtc.voiceengine.WebRtcAudioUtils; -import org.session.libsignal.service.api.messages.SignalServiceEnvelope; -import org.session.libsignal.service.api.util.StreamDetails; -import org.session.libsignal.service.internal.push.SignalServiceProtos; -import org.session.libsignal.service.loki.api.Poller; -import org.session.libsignal.service.loki.api.PushNotificationAPI; -import org.session.libsignal.service.loki.api.SnodeAPI; -import org.session.libsignal.service.loki.api.SwarmAPI; -import org.session.libsignal.service.loki.api.fileserver.FileServerAPI; -import org.session.libsignal.service.loki.api.opengroups.PublicChatAPI; -import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol; -import org.session.libsignal.service.loki.utilities.mentions.MentionsManager; import java.io.File; import java.io.FileInputStream; @@ -110,6 +108,7 @@ import java.util.Set; import dagger.ObjectGraph; import kotlin.Unit; +import kotlinx.coroutines.Job; import network.loki.messenger.BuildConfig; import static nl.komponents.kovenant.android.KovenantAndroid.startKovenant; @@ -117,7 +116,7 @@ import static nl.komponents.kovenant.android.KovenantAndroid.stopKovenant; /** * Will be called once when the TextSecure process is created. - * + *
* We're using this as an insertion point to patch up the Android PRNG disaster,
* to initialize the job manager, and to check for GCM registration freshness.
*
@@ -125,428 +124,465 @@ import static nl.komponents.kovenant.android.KovenantAndroid.stopKovenant;
*/
public class ApplicationContext extends MultiDexApplication implements DependencyInjector, DefaultLifecycleObserver {
- public static final String PREFERENCES_NAME = "SecureSMS-Preferences";
-
- private static final String TAG = ApplicationContext.class.getSimpleName();
-
- private ExpiringMessageManager expiringMessageManager;
- private TypingStatusRepository typingStatusRepository;
- private TypingStatusSender typingStatusSender;
- private JobManager jobManager;
- private ReadReceiptManager readReceiptManager;
- private ProfileManager profileManager;
- private ObjectGraph objectGraph;
- private PersistentLogger persistentLogger;
-
- // Loki
- public MessageNotifier messageNotifier = null;
- public Poller poller = null;
- public ClosedGroupPoller closedGroupPoller = null;
- public PublicChatManager publicChatManager = null;
- private PublicChatAPI publicChatAPI = null;
- public Broadcaster broadcaster = null;
- public SignalCommunicationModule communicationModule;
-
- private volatile boolean isAppVisible;
-
- public static ApplicationContext getInstance(Context context) {
- return (ApplicationContext)context.getApplicationContext();
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- Log.i(TAG, "onCreate()");
- startKovenant();
- initializeSecurityProvider();
- initializeLogging();
- initializeCrashHandling();
- initializeDependencyInjection();
- NotificationChannels.create(this);
- ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
- // Loki
- // ========
- messageNotifier = new OptimizedMessageNotifier(new DefaultMessageNotifier());
- broadcaster = new Broadcaster(this);
- LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
- LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(this);
- LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
- String userPublicKey = TextSecurePreferences.getLocalNumber(this);
- MessagingConfiguration.Companion.configure(this,
- DatabaseFactory.getStorage(this),
- DatabaseFactory.getAttachmentProvider(this),
- new SessionProtocolImpl(this));
- if (userPublicKey != null) {
- SwarmAPI.Companion.configureIfNeeded(apiDB);
- SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
- MentionsManager.Companion.configureIfNeeded(userPublicKey, threadDB, userDB);
- }
- PushNotificationAPI.Companion.configureIfNeeded(BuildConfig.DEBUG);
- setUpStorageAPIIfNeeded();
- resubmitProfilePictureIfNeeded();
- publicChatManager = new PublicChatManager(this);
- updateOpenGroupProfilePicturesIfNeeded();
- if (userPublicKey != null) {
- registerForFCMIfNeeded(false);
- }
- // Set application UI mode (day/night theme) to the user selected one.
- UiModeUtilities.setupUiModeToUserSelected(this);
- // ========
- initializeJobManager();
- initializeExpiringMessageManager();
- initializeTypingStatusRepository();
- initializeTypingStatusSender();
- initializeReadReceiptManager();
- initializeProfileManager();
- initializePeriodicTasks();
- initializeWebRtc();
- initializeBlobProvider();
- SSKEnvironment.Companion.configure(getTypingStatusRepository(), getReadReceiptManager(), getProfileManager(), messageNotifier, getExpiringMessageManager());
- }
-
- @Override
- public void onStart(@NonNull LifecycleOwner owner) {
- isAppVisible = true;
- Log.i(TAG, "App is now visible.");
- KeyCachingService.onAppForegrounded(this);
+ public static final String PREFERENCES_NAME = "SecureSMS-Preferences";
+
+ private static final String TAG = ApplicationContext.class.getSimpleName();
+
+ private ExpiringMessageManager expiringMessageManager;
+ private TypingStatusRepository typingStatusRepository;
+ private TypingStatusSender typingStatusSender;
+ private JobManager jobManager;
+ private ReadReceiptManager readReceiptManager;
+ private ProfileManager profileManager;
+ private ObjectGraph objectGraph;
+ private PersistentLogger persistentLogger;
+
// Loki
- if (poller != null) { poller.setCaughtUp(false); }
- startPollingIfNeeded();
- publicChatManager.markAllAsNotCaughtUp();
- publicChatManager.startPollersIfNeeded();
- MultiDeviceProtocol.syncConfigurationIfNeeded(this);
- }
-
- @Override
- public void onStop(@NonNull LifecycleOwner owner) {
- isAppVisible = false;
- Log.i(TAG, "App is no longer visible.");
- KeyCachingService.onAppBackgrounded(this);
- messageNotifier.setVisibleThread(-1);
+ public MessageNotifier messageNotifier = null;
+ public Poller poller = null;
+ public ClosedGroupPoller closedGroupPoller = null;
+ public PublicChatManager publicChatManager = null;
+ private PublicChatAPI publicChatAPI = null;
+ public Broadcaster broadcaster = null;
+ public SignalCommunicationModule communicationModule;
+ private Job firebaseInstanceIdJob;
+
+ private volatile boolean isAppVisible;
+
+ public static ApplicationContext getInstance(Context context) {
+ return (ApplicationContext) context.getApplicationContext();
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ Log.i(TAG, "onCreate()");
+ startKovenant();
+ initializeSecurityProvider();
+ initializeLogging();
+ initializeCrashHandling();
+ initializeDependencyInjection();
+ NotificationChannels.create(this);
+ ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
+ // Loki
+ // ========
+ messageNotifier = new OptimizedMessageNotifier(new DefaultMessageNotifier());
+ broadcaster = new Broadcaster(this);
+ LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
+ LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(this);
+ LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
+ String userPublicKey = TextSecurePreferences.getLocalNumber(this);
+ MessagingConfiguration.Companion.configure(this,
+ DatabaseFactory.getStorage(this),
+ DatabaseFactory.getAttachmentProvider(this),
+ new SessionProtocolImpl(this));
+ if (userPublicKey != null) {
+ SwarmAPI.Companion.configureIfNeeded(apiDB);
+ SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
+ MentionsManager.Companion.configureIfNeeded(userPublicKey, threadDB, userDB);
+ }
+ PushNotificationAPI.Companion.configureIfNeeded(BuildConfig.DEBUG);
+ setUpStorageAPIIfNeeded();
+ resubmitProfilePictureIfNeeded();
+ publicChatManager = new PublicChatManager(this);
+ updateOpenGroupProfilePicturesIfNeeded();
+ if (userPublicKey != null) {
+ registerForFCMIfNeeded(false);
+ }
+ // Set application UI mode (day/night theme) to the user selected one.
+ UiModeUtilities.setupUiModeToUserSelected(this);
+ // ========
+ initializeJobManager();
+ initializeExpiringMessageManager();
+ initializeTypingStatusRepository();
+ initializeTypingStatusSender();
+ initializeReadReceiptManager();
+ initializeProfileManager();
+ initializePeriodicTasks();
+ initializeWebRtc();
+ initializeBlobProvider();
+ SSKEnvironment.Companion.configure(getTypingStatusRepository(), getReadReceiptManager(), getProfileManager(), messageNotifier, getExpiringMessageManager());
+ }
+
+ @Override
+ public void onStart(@NonNull LifecycleOwner owner) {
+ isAppVisible = true;
+ Log.i(TAG, "App is now visible.");
+ KeyCachingService.onAppForegrounded(this);
+ // Loki
+ if (poller != null) {
+ poller.setCaughtUp(false);
+ }
+ startPollingIfNeeded();
+ publicChatManager.markAllAsNotCaughtUp();
+ publicChatManager.startPollersIfNeeded();
+ MultiDeviceProtocol.syncConfigurationIfNeeded(this);
+ }
+
+ @Override
+ public void onStop(@NonNull LifecycleOwner owner) {
+ isAppVisible = false;
+ Log.i(TAG, "App is no longer visible.");
+ KeyCachingService.onAppBackgrounded(this);
+ messageNotifier.setVisibleThread(-1);
+ // Loki
+ if (poller != null) {
+ poller.stopIfNeeded();
+ }
+ if (closedGroupPoller != null) {
+ closedGroupPoller.stopIfNeeded();
+ }
+ if (publicChatManager != null) {
+ publicChatManager.stopPollers();
+ }
+ }
+
+ @Override
+ public void onTerminate() {
+ stopKovenant(); // Loki
+ super.onTerminate();
+ }
+
+ @Override
+ public void injectDependencies(Object object) {
+ if (object instanceof InjectableType) {
+ objectGraph.inject(object);
+ }
+ }
+
+ public void initializeLocaleParser() {
+ LocaleParser.Companion.configure(new LocaleParseHelper());
+ }
+
+ public JobManager getJobManager() {
+ return jobManager;
+ }
+
+ public ExpiringMessageManager getExpiringMessageManager() {
+ return expiringMessageManager;
+ }
+
+ public TypingStatusRepository getTypingStatusRepository() {
+ return typingStatusRepository;
+ }
+
+ public TypingStatusSender getTypingStatusSender() {
+ return typingStatusSender;
+ }
+
+ public ReadReceiptManager getReadReceiptManager() {
+ return readReceiptManager;
+ }
+
+ public ProfileManager getProfileManager() {
+ return profileManager;
+ }
+
+ public boolean isAppVisible() {
+ return isAppVisible;
+ }
+
+ public PersistentLogger getPersistentLogger() {
+ return persistentLogger;
+ }
+
// Loki
- if (poller != null) { poller.stopIfNeeded(); }
- if (closedGroupPoller != null) { closedGroupPoller.stopIfNeeded(); }
- if (publicChatManager != null) { publicChatManager.stopPollers(); }
- }
-
- @Override
- public void onTerminate() {
- stopKovenant(); // Loki
- super.onTerminate();
- }
-
- @Override
- public void injectDependencies(Object object) {
- if (object instanceof InjectableType) {
- objectGraph.inject(object);
- }
- }
-
- public void initializeLocaleParser() {
- LocaleParser.Companion.configure(new LocaleParseHelper());
- }
-
- public JobManager getJobManager() {
- return jobManager;
- }
-
- public ExpiringMessageManager getExpiringMessageManager() {
- return expiringMessageManager;
- }
-
- public TypingStatusRepository getTypingStatusRepository() {
- return typingStatusRepository;
- }
-
- public TypingStatusSender getTypingStatusSender() {
- return typingStatusSender;
- }
-
- public ReadReceiptManager getReadReceiptManager() { return readReceiptManager; }
-
- public ProfileManager getProfileManager() { return profileManager; }
-
- public boolean isAppVisible() {
- return isAppVisible;
- }
-
- public PersistentLogger getPersistentLogger() {
- return persistentLogger;
- }
-
- // Loki
- public @Nullable PublicChatAPI getPublicChatAPI() {
- if (publicChatAPI != null || !IdentityKeyUtil.hasIdentityKey(this)) { return publicChatAPI; }
- String userPublicKey = TextSecurePreferences.getLocalNumber(this);
- if (userPublicKey== null) { return publicChatAPI; }
- byte[] userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(this).getPrivateKey().serialize();
- LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(this);
- LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
- GroupDatabase groupDB = DatabaseFactory.getGroupDatabase(this);
- publicChatAPI = new PublicChatAPI(userPublicKey, userPrivateKey, apiDB, userDB, groupDB);
- return publicChatAPI;
- }
-
- private void initializeSecurityProvider() {
- try {
- Class.forName("org.signal.aesgcmprovider.AesGcmCipher");
- } catch (ClassNotFoundException e) {
- Log.e(TAG, "Failed to find AesGcmCipher class");
- throw new ProviderInitializationException();
- }
-
- int aesPosition = Security.insertProviderAt(new AesGcmProvider(), 1);
- Log.i(TAG, "Installed AesGcmProvider: " + aesPosition);
-
- if (aesPosition < 0) {
- Log.e(TAG, "Failed to install AesGcmProvider()");
- throw new ProviderInitializationException();
- }
-
- int conscryptPosition = Security.insertProviderAt(Conscrypt.newProvider(), 2);
- Log.i(TAG, "Installed Conscrypt provider: " + conscryptPosition);
-
- if (conscryptPosition < 0) {
- Log.w(TAG, "Did not install Conscrypt provider. May already be present.");
- }
- }
-
- private void initializeLogging() {
- persistentLogger = new PersistentLogger(this);
- Log.initialize(new AndroidLogger(), persistentLogger);
- }
-
- private void initializeCrashHandling() {
- final Thread.UncaughtExceptionHandler originalHandler = Thread.getDefaultUncaughtExceptionHandler();
- Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionLogger(originalHandler));
- }
-
- private void initializeJobManager() {
- this.jobManager = new JobManager(this, new JobManager.Configuration.Builder()
- .setDataSerializer(new JsonDataSerializer())
- .setJobFactories(JobManagerFactories.getJobFactories(this))
- .setConstraintFactories(JobManagerFactories.getConstraintFactories(this))
- .setConstraintObservers(JobManagerFactories.getConstraintObservers(this))
- .setJobStorage(new FastJobStorage(DatabaseFactory.getJobDatabase(this)))
- .setDependencyInjector(this)
- .build());
- }
-
- private void initializeDependencyInjection() {
- communicationModule = new SignalCommunicationModule(this);
- this.objectGraph = ObjectGraph.create(communicationModule);
- }
-
-
- private void initializeExpiringMessageManager() {
- this.expiringMessageManager = new ExpiringMessageManager(this);
- }
-
- private void initializeTypingStatusRepository() {
- this.typingStatusRepository = new TypingStatusRepository();
- }
-
- private void initializeReadReceiptManager() {
- this.readReceiptManager = new ReadReceiptManager();
- }
-
- private void initializeProfileManager() {
- this.profileManager = new ProfileManager();
- }
-
- private void initializeTypingStatusSender() {
- this.typingStatusSender = new TypingStatusSender(this);
- }
-
- private void initializePeriodicTasks() {
- LocalBackupListener.schedule(this);
- BackgroundPollWorker.schedulePeriodic(this); // Loki
-
- if (BuildConfig.PLAY_STORE_DISABLED) {
- UpdateApkRefreshListener.schedule(this);
- }
- }
-
- private void initializeWebRtc() {
- try {
- Set