From d0e781ccb44c443886dd357c1b2ab11260ef1ad6 Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Thu, 21 Sep 2017 11:27:53 -0700 Subject: [PATCH] Sync read receipt configuration to sibling devices // FREEBIE --- build.gradle | 6 +- .../SignalCommunicationModule.java | 4 +- .../jobs/MultiDeviceReadReceiptUpdateJob.java | 58 +++++++++++++++++++ .../AppProtectionPreferenceFragment.java | 16 +++++ .../securesms/util/TextSecurePreferences.java | 2 +- 5 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 src/org/thoughtcrime/securesms/jobs/MultiDeviceReadReceiptUpdateJob.java diff --git a/build.gradle b/build.gradle index a3352df273..3a5cb9954f 100644 --- a/build.gradle +++ b/build.gradle @@ -63,7 +63,7 @@ dependencies { compile 'org.whispersystems:jobmanager:1.0.2' compile 'org.whispersystems:libpastelog:1.0.7' - compile 'org.whispersystems:signal-service-android:2.6.6' + compile 'org.whispersystems:signal-service-android:2.6.7' compile 'org.whispersystems:webrtc-android:M59-S1' compile "me.leolin:ShortcutBadger:1.1.16" @@ -145,7 +145,7 @@ dependencyVerification { 'com.google.android.exoplayer:exoplayer:955085aa611a8f7cf6c61b88ae03d1a392f4ad94c9bfbc153f3dedb9ffb14718', 'org.whispersystems:jobmanager:506f679fc2fcf7bb6d10f00f41d6f6ea0abf75c70dc95b913398661ad538a181', 'org.whispersystems:libpastelog:bb331d9a98240fc139101128ba836c1edec3c40e000597cdbb29ebf4cbf34d88', - 'org.whispersystems:signal-service-android:731fc8c45f38f42b2d0da1053cf32adcd175708e0c126571150690637108971a', + 'org.whispersystems:signal-service-android:cdeb7bfc4ae3fe744fc6e56e36f1ed3b94681b9f1e61aa2c031d703808a03c58', 'org.whispersystems:webrtc-android:de647643afbbea45a26a4f24db75aa10bc8de45426e8eb0d9d563cc10af4f582', 'me.leolin:ShortcutBadger:e3cb3e7625892129b0c92dd5e4bc649faffdd526d5af26d9c45ee31ff8851774', 'se.emilsjolander:stickylistheaders:a08ca948aa6b220f09d82f16bbbac395f6b78897e9eeac6a9f0b0ba755928eeb', @@ -182,7 +182,7 @@ dependencyVerification { 'com.google.android.gms:play-services-basement:95dd882c5ffba15b9a99de3fefb05d3a01946623af67454ca00055d222f85a8d', 'com.google.android.gms:play-services-iid:54e919f9957b8b7820da7ee9b83471d00d0cac1cf08ddea8b5b41aea80bb1a70', 'org.whispersystems:signal-protocol-android:5b8acded7f2a40178eb90ab8e8cbfec89d170d91b3ff5e78487d1098df6185a1', - 'org.whispersystems:signal-service-java:90aadf941cc31cb0f5af9e1adffa248556f1cfc56a62c141bc62812e7bf3ed52', + 'org.whispersystems:signal-service-java:9321c7394977fa6f21b85297dc1acaa4b027f655ac376636b343dabda35f3774', 'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a', 'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'com.klinkerapps:logger:177e325259a8b111ad6745ec10db5861723c99f402222b80629f576f49408541', diff --git a/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java b/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java index b32f7c02b8..bc36f73033 100644 --- a/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java +++ b/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java @@ -15,6 +15,7 @@ import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob; import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob; import org.thoughtcrime.securesms.jobs.MultiDeviceGroupUpdateJob; import org.thoughtcrime.securesms.jobs.MultiDeviceProfileKeyUpdateJob; +import org.thoughtcrime.securesms.jobs.MultiDeviceReadReceiptUpdateJob; import org.thoughtcrime.securesms.jobs.MultiDeviceReadUpdateJob; import org.thoughtcrime.securesms.jobs.MultiDeviceVerifiedUpdateJob; import org.thoughtcrime.securesms.jobs.PushGroupSendJob; @@ -69,7 +70,8 @@ import dagger.Provides; CreateProfileActivity.class, RetrieveProfileAvatarJob.class, MultiDeviceProfileKeyUpdateJob.class, - SendReadReceiptJob.class}) + SendReadReceiptJob.class, + MultiDeviceReadReceiptUpdateJob.class}) public class SignalCommunicationModule { private final Context context; diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadReceiptUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadReceiptUpdateJob.java new file mode 100644 index 0000000000..f1fcb6f918 --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadReceiptUpdateJob.java @@ -0,0 +1,58 @@ +package org.thoughtcrime.securesms.jobs; + + +import android.content.Context; +import android.util.Log; + +import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.whispersystems.jobqueue.JobParameters; +import org.whispersystems.jobqueue.requirements.NetworkRequirement; +import org.whispersystems.libsignal.util.guava.Optional; +import org.whispersystems.signalservice.api.SignalServiceMessageSender; +import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; +import org.whispersystems.signalservice.api.messages.multidevice.ConfigurationMessage; +import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage; +import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; + +import java.io.IOException; + +import javax.inject.Inject; + +public class MultiDeviceReadReceiptUpdateJob extends ContextJob implements InjectableType { + + private static final long serialVersionUID = 1L; + + private static final String TAG = MultiDeviceReadReceiptUpdateJob.class.getSimpleName(); + + @Inject transient SignalServiceMessageSender messageSender; + + private final boolean enabled; + + public MultiDeviceReadReceiptUpdateJob(Context context, boolean enabled) { + super(context, JobParameters.newBuilder() + .withPersistence() + .withGroupId("__MULTI_DEVICE_READ_RECEIPT_UPDATE_JOB__") + .withRequirement(new NetworkRequirement(context)) + .create()); + + this.enabled = enabled; + } + + @Override + public void onAdded() {} + + @Override + public void onRun() throws IOException, UntrustedIdentityException { + messageSender.sendMessage(SignalServiceSyncMessage.forConfiguration(new ConfigurationMessage(Optional.of(enabled)))); + } + + @Override + public boolean onShouldRetry(Exception e) { + return e instanceof PushNetworkException; + } + + @Override + public void onCanceled() { + Log.w(TAG, "**** Failed to synchronize read receipts state!"); + } +} diff --git a/src/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java b/src/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java index b9a694f7b3..5fcc51244e 100644 --- a/src/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java +++ b/src/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java @@ -16,12 +16,14 @@ import android.widget.Toast; import com.doomonafireball.betterpickers.hmspicker.HmsPickerBuilder; import com.doomonafireball.betterpickers.hmspicker.HmsPickerDialogFragment; +import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.ApplicationPreferencesActivity; import org.thoughtcrime.securesms.BlockedContactsActivity; import org.thoughtcrime.securesms.PassphraseChangeActivity; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecretUtil; +import org.thoughtcrime.securesms.jobs.MultiDeviceReadReceiptUpdateJob; import org.thoughtcrime.securesms.service.KeyCachingService; import org.thoughtcrime.securesms.util.TextSecurePreferences; @@ -45,6 +47,8 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment .setOnPreferenceClickListener(new ChangePassphraseClickListener()); this.findPreference(TextSecurePreferences.PASSPHRASE_TIMEOUT_INTERVAL_PREF) .setOnPreferenceClickListener(new PassphraseIntervalClickListener()); + this.findPreference(TextSecurePreferences.READ_RECEIPTS_PREF) + .setOnPreferenceChangeListener(new ReadReceiptToggleListener()); this.findPreference(PREFERENCE_CATEGORY_BLOCKED) .setOnPreferenceClickListener(new BlockedContactsClickListener()); disablePassphrase @@ -170,6 +174,18 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment } } + private class ReadReceiptToggleListener implements Preference.OnPreferenceChangeListener { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + boolean enabled = (boolean)newValue; + ApplicationContext.getInstance(getContext()) + .getJobManager() + .add(new MultiDeviceReadReceiptUpdateJob(getContext(), enabled)); + + return true; + } + } + public static CharSequence getSummary(Context context) { final int privacySummaryResId = R.string.ApplicationPreferencesActivity_privacy_summary; final String onRes = context.getString(R.string.ApplicationPreferencesActivity_on); diff --git a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java index 91e19ddb60..ab6e5c1a66 100644 --- a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java +++ b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java @@ -113,7 +113,7 @@ public class TextSecurePreferences { private static final String ALWAYS_RELAY_CALLS_PREF = "pref_turn_only"; private static final String PROFILE_KEY_PREF = "pref_profile_key"; private static final String PROFILE_NAME_PREF = "pref_profile_name"; - private static final String READ_RECEIPTS_PREF = "pref_read_receipts"; + public static final String READ_RECEIPTS_PREF = "pref_read_receipts"; public static boolean isReadReceiptsEnabled(Context context) { return getBooleanPreference(context, READ_RECEIPTS_PREF, false);