Skip to content

Commit

Permalink
wip: Refactor UnifiedPush
Browse files Browse the repository at this point in the history
  • Loading branch information
valldrac committed Oct 11, 2024
1 parent 1c471ae commit f338f53
Show file tree
Hide file tree
Showing 25 changed files with 320 additions and 240 deletions.
2 changes: 1 addition & 1 deletion app/proguard/proguard.cfg
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
-dontobfuscate
-keepattributes SourceFile,LineNumberTable
-keep class org.whispersystems.** { *; }
-keep class im.molly.** { *; }
-keep class org.signal.libsignal.net.** { *; }
-keep class org.signal.libsignal.protocol.** { *; }
-keep class org.signal.libsignal.usernames.** { *; }
-keep class org.thoughtcrime.securesms.** { *; }
-keep class org.signal.donations.json.** { *; }
-keep class im.molly.unifiedpush.** { *; }
-keepclassmembers class ** {
public void onEvent*(**);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.annotation.WorkerThread;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;

import com.bumptech.glide.Glide;
Expand Down Expand Up @@ -89,6 +90,7 @@
import org.thoughtcrime.securesms.mms.SignalGlideModule;
import org.thoughtcrime.securesms.net.NetworkManager;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.notifications.NotificationIds;
import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.ratelimit.RateLimitUtil;
import org.thoughtcrime.securesms.recipients.Recipient;
Expand All @@ -111,7 +113,6 @@
import org.thoughtcrime.securesms.util.RemoteConfig;
import org.thoughtcrime.securesms.util.FileUtils;
import org.thoughtcrime.securesms.util.PlayServicesUtil;
import org.thoughtcrime.securesms.util.RemoteConfig;
import org.thoughtcrime.securesms.util.SignalLocalMetrics;
import org.thoughtcrime.securesms.util.SignalUncaughtExceptionHandler;
import org.thoughtcrime.securesms.util.StorageUtil;
Expand Down Expand Up @@ -203,7 +204,7 @@ private void onCreateUnlock() {
.addBlocking("scrubber", () -> Scrubber.setIdentifierHmacKeyProvider(() -> SignalStore.svr().getOrCreateMasterKey().deriveLoggingKey()))
.addBlocking("network-settings", this::initializeNetworkSettings)
.addBlocking("first-launch", this::initializeFirstEverAppLaunch)
.addBlocking("gcm-check", this::initializeFcmCheck)
.addBlocking("push", this::updatePushNotificationServices)
.addBlocking("app-migrations", this::initializeApplicationMigrations)
.addBlocking("lifecycle-observer", () -> AppForegroundObserver.addListener(this))
.addBlocking("message-retriever", this::initializeMessageRetrieval)
Expand Down Expand Up @@ -429,11 +430,11 @@ private void initializeApplicationMigrations() {
ApplicationMigrations.onApplicationCreate(this, AppDependencies.getJobManager());
}

public void initializeMessageRetrieval() {
private void initializeMessageRetrieval() {
AppDependencies.getIncomingMessageObserver();
}

public void finalizeMessageRetrieval() {
private void finalizeMessageRetrieval() {
AppDependencies.resetNetwork(false);
}

Expand Down Expand Up @@ -497,39 +498,33 @@ private void initializeNetworkSettings() {
}
}

// MOLLY: this initialize FCM, websocket and UnifiedPush
public void initializeFcmCheck() {
@MainThread
public void updatePushNotificationServices() {
if (!SignalStore.account().isRegistered()) {
return;
}

PlayServicesUtil.PlayServicesStatus fcmStatus = PlayServicesUtil.getPlayServicesStatus(this);
boolean unifiedPushAvailable = UnifiedPushHelper.isUnifiedPushAvailable();
boolean forceWebSocket = SignalStore.internal().isWebsocketModeForced();

if (unifiedPushAvailable || forceWebSocket
|| fcmStatus == PlayServicesUtil.PlayServicesStatus.DISABLED) {
if (unifiedPushAvailable && !SignalStore.unifiedpush().getAirGaped()) {
AppDependencies.getJobManager().add(new UnifiedPushRefreshJob());
}
AppDependencies.getJobManager().cancel(new FcmRefreshJob().getId());
if (SignalStore.account().isFcmEnabled()) {
boolean fcmEnabled = SignalStore.account().isFcmEnabled();
boolean unifiedPushEnabled = SignalStore.unifiedpush().isEnabled();
boolean forceWebSocket = SignalStore.internal().isWebsocketModeForced();

if (unifiedPushEnabled || forceWebSocket || fcmStatus == PlayServicesUtil.PlayServicesStatus.DISABLED) {
if (fcmEnabled) {
Log.i(TAG, "Play Services are disabled. Disabling FCM.");
SignalStore.account().setFcmEnabled(false);
SignalStore.account().setFcmToken(null);
SignalStore.account().setFcmTokenLastSetTime(-1);
AppDependencies.getJobManager().add(new RefreshAttributesJob());
updateFcmStatus(false);
} else {
Log.d(TAG, "FCM is disabled.");
SignalStore.account().setFcmTokenLastSetTime(-1);
}
} else if (fcmStatus == PlayServicesUtil.PlayServicesStatus.SUCCESS &&
!SignalStore.account().isFcmEnabled() &&
if (unifiedPushEnabled) {
AppDependencies.getJobManager().add(new UnifiedPushRefreshJob());
}
} else if (fcmStatus == PlayServicesUtil.PlayServicesStatus.SUCCESS && !fcmEnabled &&
SignalStore.account().getFcmTokenLastSetTime() < 0) {
Log.i(TAG, "Play Services are newly-available. Updating to use FCM.");
SignalStore.account().setFcmEnabled(true);
AppDependencies.getJobManager().startChain(new FcmRefreshJob())
.then(new RefreshAttributesJob())
.enqueue();
updateFcmStatus(true);
} else {
long lastSetTime = SignalStore.account().getFcmTokenLastSetTime();
long nextSetTime = lastSetTime + TimeUnit.HOURS.toMillis(6);
Expand All @@ -547,6 +542,16 @@ public void initializeFcmCheck() {
}
}

private void updateFcmStatus(boolean fcmEnabled) {
SignalStore.account().setFcmEnabled(fcmEnabled);
if (!fcmEnabled) {
NotificationManagerCompat.from(this).cancel(NotificationIds.FCM_FAILURE);
}
AppDependencies.getJobManager().startChain(new FcmRefreshJob())
.then(new RefreshAttributesJob())
.enqueue();
}

private void initializeExpiringMessageManager() {
AppDependencies.getExpiringMessageManager().checkSchedule();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ import java.util.UUID
import java.util.concurrent.TimeUnit
import kotlin.math.max
import kotlin.random.Random
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds

class InternalSettingsFragment : DSLSettingsFragment(R.string.preferences__internal_preferences) {

Expand Down Expand Up @@ -356,25 +354,6 @@ class InternalSettingsFragment : DSLSettingsFragment(R.string.preferences__inter

sectionHeaderPref(DSLSettingsText.from("Network"))

switchPref(
title = DSLSettingsText.from("Force websocket mode"),
summary = DSLSettingsText.from("Pretend you have no Play Services. Ignores websocket messages and keeps the websocket open in a foreground service. You have to manually force-stop the app for changes to take effect."),
isChecked = state.forceWebsocketMode,
onClick = {
viewModel.setForceWebsocketMode(!state.forceWebsocketMode)
SimpleTask.run({
val jobState = AppDependencies.jobManager.runSynchronously(RefreshAttributesJob(), 10.seconds.inWholeMilliseconds)
return@run jobState.isPresent && jobState.get().isComplete
}, { success ->
if (success) {
Toast.makeText(context, "Successfully refreshed attributes. Force-stop the app for changes to take effect.", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(context, "Failed to refresh attributes.", Toast.LENGTH_SHORT).show()
}
})
}
)

switchPref(
title = DSLSettingsText.from("Allow censorship circumvention toggle"),
summary = DSLSettingsText.from("Allow changing the censorship circumvention toggle regardless of network connectivity."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,6 @@ class InternalSettingsViewModel(private val repository: InternalSettingsReposito
refresh()
}

fun setForceWebsocketMode(enabled: Boolean) {
preferenceDataStore.putBoolean(InternalValues.FORCE_WEBSOCKET_MODE, enabled)
refresh()
}

fun setUseBuiltInEmoji(enabled: Boolean) {
preferenceDataStore.putBoolean(InternalValues.FORCE_BUILT_IN_EMOJI, enabled)
refresh()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.signal.core.util.getParcelableExtraCompat
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.BuildConfig
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.PromptBatterySaverDialogFragment
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
Expand All @@ -43,6 +44,8 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.notifications.NotificationChannels
import org.thoughtcrime.securesms.notifications.TurnOnNotificationsBottomSheet
import org.thoughtcrime.securesms.util.BottomSheetUtil
import org.thoughtcrime.securesms.util.CommunicationActions
import org.thoughtcrime.securesms.util.PlayServicesUtil
import org.thoughtcrime.securesms.util.RingtoneUtil
import org.thoughtcrime.securesms.util.SecurePreferenceManager
import org.thoughtcrime.securesms.util.ViewUtil
Expand Down Expand Up @@ -71,10 +74,10 @@ class NotificationsSettingsFragment : DSLSettingsFragment(R.string.preferences__
private val ledBlinkValues by lazy { resources.getStringArray(R.array.pref_led_blink_pattern_values) }
private val ledBlinkLabels by lazy { resources.getStringArray(R.array.pref_led_blink_pattern_entries) }

private val notificationMethodValues = NotificationDeliveryMethod.values().filterNot {
!SignalStore.account.fcmEnabled && it == NotificationDeliveryMethod.FCM
private val notificationMethodValues = NotificationDeliveryMethod.entries.filterNot { method ->
method == NotificationDeliveryMethod.FCM && !BuildConfig.USE_PLAY_SERVICES
}
private val notificationMethodLabels by lazy { notificationMethodValues.map { resources.getString(it.getStringId()) }.toTypedArray() }
private val notificationMethodLabels by lazy { notificationMethodValues.map { resources.getString(it.stringId) }.toTypedArray() }

private lateinit var viewModel: NotificationsSettingsViewModel

Expand Down Expand Up @@ -336,31 +339,86 @@ class NotificationsSettingsFragment : DSLSettingsFragment(R.string.preferences__

dividerPref()

sectionHeaderPref(R.string.NotificationsSettingsFragment__pushStrategy)
sectionHeaderPref(R.string.NotificationsSettingsFragment__push_notifications)

textPref(
summary = DSLSettingsText.from(R.string.NotificationsSettingsFragment__preferred_method_for_receiving_notifications_from_the_signal_service)
)

val showAlertIcon = when (state.preferredNotificationMethod) {
NotificationDeliveryMethod.FCM -> !state.canReceiveFcm
NotificationDeliveryMethod.WEBSOCKET -> false
NotificationDeliveryMethod.UNIFIEDPUSH -> !state.canReceiveUnifiedPush
}
radioListPref(
title = DSLSettingsText.from(R.string.NotificationsSettingsFragment__deliveryMethod),
title = DSLSettingsText.from(R.string.NotificationsSettingsFragment__delivery_method),
listItems = notificationMethodLabels,
selected = notificationMethodValues.indexOf(state.notificationDeliveryMethod),
isEnabled = !state.isLinkedDevice,
selected = notificationMethodValues.indexOf(state.preferredNotificationMethod),
isEnabled = !state.isLinkedDevice, // MOLLY: TODO
iconEnd = if (showAlertIcon) DSLSettingsIcon.from(R.drawable.ic_alert) else null,
onSelected = {
viewModel.setNotificationDeliveryMethod(notificationMethodValues[it])
onNotificationMethodChanged(notificationMethodValues[it], state.preferredNotificationMethod)
}
)

val unifiedPushEnabled = state.notificationDeliveryMethod == NotificationDeliveryMethod.UNIFIEDPUSH
clickPref(
title = DSLSettingsText.from(R.string.NotificationsSettingsFragment__unifiedpush),
summary = DSLSettingsText.from(R.string.NotificationsSettingsFragment__unifiedpushDescription),
isEnabled = unifiedPushEnabled,
iconEnd = if (unifiedPushEnabled && !state.unifiedPushOk) DSLSettingsIcon.from(R.drawable.ic_alert) else null,
title = DSLSettingsText.from(R.string.NotificationsSettingsFragment__configure_unifiedpush),
isEnabled = state.preferredNotificationMethod == NotificationDeliveryMethod.UNIFIEDPUSH,
onClick = {
findNavController().safeNavigate(R.id.action_notificationsSettingsFragment_to_unifiedPushFragment)
navigateToUnifiedPushSettings()
}
)
}
}

private fun onNotificationMethodChanged(
method: NotificationDeliveryMethod,
previousMethod: NotificationDeliveryMethod
) {
when (method) {
NotificationDeliveryMethod.FCM -> {
viewModel.setPreferredNotificationMethod(method)
val msgId = when (viewModel.fcmState) {
PlayServicesUtil.PlayServicesStatus.SUCCESS -> null
PlayServicesUtil.PlayServicesStatus.DISABLED -> R.string.RegistrationActivity_missing_google_play_services
PlayServicesUtil.PlayServicesStatus.MISSING -> R.string.RegistrationActivity_missing_google_play_services
PlayServicesUtil.PlayServicesStatus.NEEDS_UPDATE -> R.string.RegistrationActivity_google_play_services_is_updating_or_unavailable
PlayServicesUtil.PlayServicesStatus.TRANSIENT_ERROR -> R.string.RegistrationActivity_play_services_error
}
if (msgId != null) {
Toast.makeText(requireContext(), getString(msgId), Toast.LENGTH_LONG).show()
}
}

NotificationDeliveryMethod.WEBSOCKET -> {
viewModel.setPreferredNotificationMethod(method)
}

NotificationDeliveryMethod.UNIFIEDPUSH -> {
if (method != previousMethod) {
MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.NotificationsSettingsFragment__mollysocket_server)
.setMessage(R.string.NotificationsSettingsFragment__to_use_unifiedpush_you_need_a_mollysocket_server)
.setPositiveButton(R.string.yes) { _, _ ->
viewModel.setPreferredNotificationMethod(method)
navigateToUnifiedPushSettings()
}
.setNegativeButton(R.string.no, null)
.setNeutralButton(R.string.LearnMoreTextView_learn_more) { _, _ ->
CommunicationActions.openBrowserLink(requireContext(), getString(R.string.mollysocket_setup_url))
}
.show()
} else {
navigateToUnifiedPushSettings()
}
}
}
}

private fun navigateToUnifiedPushSettings() {
findNavController().safeNavigate(R.id.action_notificationsSettingsFragment_to_unifiedPushFragment)
}

private fun getRingtoneSummary(uri: Uri): String {
return if (TextUtils.isEmpty(uri.toString())) {
getString(R.string.preferences__silent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import android.net.Uri
import org.thoughtcrime.securesms.keyvalue.SettingsValues.NotificationDeliveryMethod

data class NotificationsSettingsState(
val isLinkedDevice: Boolean,
val messageNotificationsState: MessageNotificationsState,
val callNotificationsState: CallNotificationsState,
val notifyWhileLocked: Boolean,
val canEnableNotifyWhileLocked: Boolean,
val notifyWhenContactJoinsSignal: Boolean,
val notificationDeliveryMethod: NotificationDeliveryMethod,
val unifiedPushOk: Boolean,
val isLinkedDevice: Boolean,
val preferredNotificationMethod: NotificationDeliveryMethod,
val canReceiveFcm: Boolean,
val canReceiveUnifiedPush: Boolean,
)

data class MessageNotificationsState(
Expand Down
Loading

0 comments on commit f338f53

Please sign in to comment.