diff --git a/build.gradle b/build.gradle
index c806f99c8..58a1192b3 100644
--- a/build.gradle
+++ b/build.gradle
@@ -77,7 +77,7 @@ dependencies {
compile 'com.google.android.exoplayer:exoplayer-core:2.8.4'
compile 'com.google.android.exoplayer:exoplayer-ui:2.8.4'
- compile 'org.whispersystems:signal-service-android:2.7.6'
+ compile 'org.whispersystems:signal-service-android:2.8.1'
compile 'org.whispersystems:webrtc-android:M69'
compile "me.leolin:ShortcutBadger:1.1.16"
@@ -171,7 +171,7 @@ dependencyVerification {
'com.google.android.gms:play-services-maps:45e8021e7ddac4a44a82a0e9698991389ded3023d35c58f38dbd86d54211ec0e',
'com.google.android.exoplayer:exoplayer-ui:027557b2d69b15e1852a2530b36971f0dcc177abae240ee35e05f63502cdb0a7',
'com.google.android.exoplayer:exoplayer-core:e69b409e11887c955deb373357c30eeabf183395db0092b4817e0f80bb467d5b',
- 'org.whispersystems:signal-service-android:823eed29e64fb0aa30d2078cb5ec0245e2a0713a4028121329c5c28788ef27f8',
+ 'org.whispersystems:signal-service-android:414e91598abd941eb3be9a85702538cc9928d8c22f00e07716b83a096cbbe54d',
'org.whispersystems:webrtc-android:5493c92141ce884fc5ce8240d783232f4fe14bd17a8d0d7d1bd4944d0bd1682f',
'me.leolin:ShortcutBadger:e3cb3e7625892129b0c92dd5e4bc649faffdd526d5af26d9c45ee31ff8851774',
'se.emilsjolander:stickylistheaders:a08ca948aa6b220f09d82f16bbbac395f6b78897e9eeac6a9f0b0ba755928eeb',
@@ -218,7 +218,7 @@ dependencyVerification {
'com.github.bumptech.glide:gifdecoder:59ccf3bb0cec11dab4b857382cbe0b171111b6fc62bf141adce4e1180889af15',
'com.android.support:support-annotations:af05330d997eb92a066534dbe0a3ea24347d26d7001221092113ae02a8f233da',
'org.whispersystems:signal-protocol-android:5b8acded7f2a40178eb90ab8e8cbfec89d170d91b3ff5e78487d1098df6185a1',
- 'org.whispersystems:signal-service-java:6169643c65dcba8c784744006fc3afd9b6f309041b310a33a624121e3577433a',
+ 'org.whispersystems:signal-service-java:c7ab92374e9656ba86a8d859cec71d03a68bba3e7ec0b7c597b726bf720eac21',
'com.github.bumptech.glide:disklrucache:c1b1b6f5bbd01e2fcdc9d7f60913c8d338bdb65ed4a93bfa02b56f19daaade4b',
'com.github.bumptech.glide:annotations:bede99ef9f71517a4274bac18fd3e483e9f2b6108d7d6fe8f4949be4aa4d9512',
'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a',
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f0c37757a..0bf3d1287 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -148,7 +148,9 @@
Error leaving group
Please choose a contact
Unblock this contact?
+ Unblock this group?
You will once again be able to receive messages and calls from this contact.
+ Existing members will be able to add you to the group again.
Unblock
Attachment exceeds size limits for the type of message you\'re sending.
Camera unavailable
@@ -479,9 +481,15 @@
Block this contact?
You will no longer receive messages and calls from this contact.
+ Block and leave this group?
+ Block this group?
+ You will no longer receive messages or updates from this group.
Block
Unblock this contact?
You will once again be able to receive messages and calls from this contact.
+ Unblock this group?
+ Existing members will be able to add you to the group again.
+ Error leaving group
Unblock
Enabled
Disabled
diff --git a/src/org/thoughtcrime/securesms/ConversationActivity.java b/src/org/thoughtcrime/securesms/ConversationActivity.java
index 339fb7694..bf551a1ac 100644
--- a/src/org/thoughtcrime/securesms/ConversationActivity.java
+++ b/src/org/thoughtcrime/securesms/ConversationActivity.java
@@ -51,6 +51,8 @@ import android.support.v7.app.AlertDialog;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
+
+import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.logging.Log;
import android.util.Pair;
import android.view.KeyEvent;
@@ -70,7 +72,6 @@ import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.location.places.ui.PlacePicker;
-import com.google.protobuf.ByteString;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -192,7 +193,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import static org.thoughtcrime.securesms.TransportOption.Type;
import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
import static org.whispersystems.libsignal.SessionCipher.SESSION_LOCK;
-import static org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
/**
* Activity for displaying a message thread, as well as
@@ -693,26 +693,34 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
private void handleUnblock() {
+ int titleRes = R.string.ConversationActivity_unblock_this_contact_question;
+ int bodyRes = R.string.ConversationActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact;
+
+ if (recipient.isGroupRecipient()) {
+ titleRes = R.string.ConversationActivity_unblock_this_group_question;
+ bodyRes = R.string.ConversationActivity_unblock_this_group_description;
+ }
+
//noinspection CodeBlock2Expr
new AlertDialog.Builder(this)
- .setTitle(R.string.ConversationActivity_unblock_this_contact_question)
- .setMessage(R.string.ConversationActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact)
- .setNegativeButton(android.R.string.cancel, null)
- .setPositiveButton(R.string.ConversationActivity_unblock, (dialog, which) -> {
- new AsyncTask() {
- @Override
- protected Void doInBackground(Void... params) {
- DatabaseFactory.getRecipientDatabase(ConversationActivity.this)
+ .setTitle(titleRes)
+ .setMessage(bodyRes)
+ .setNegativeButton(android.R.string.cancel, null)
+ .setPositiveButton(R.string.ConversationActivity_unblock, (dialog, which) -> {
+ new AsyncTask() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ DatabaseFactory.getRecipientDatabase(ConversationActivity.this)
.setBlocked(recipient, false);
- ApplicationContext.getInstance(ConversationActivity.this)
- .getJobManager()
- .add(new MultiDeviceBlockedUpdateJob(ConversationActivity.this));
+ ApplicationContext.getInstance(ConversationActivity.this)
+ .getJobManager()
+ .add(new MultiDeviceBlockedUpdateJob(ConversationActivity.this));
- return null;
- }
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- }).show();
+ return null;
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }).show();
}
@TargetApi(Build.VERSION_CODES.KITKAT)
@@ -847,24 +855,21 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
builder.setCancelable(true);
builder.setMessage(getString(R.string.ConversationActivity_are_you_sure_you_want_to_leave_this_group));
builder.setPositiveButton(R.string.yes, (dialog, which) -> {
- Context self = ConversationActivity.this;
+ Recipient groupRecipient = getRecipient();
+ long threadId = DatabaseFactory.getThreadDatabase(this).getThreadIdFor(groupRecipient);
+ Optional leaveMessage = GroupUtil.createGroupLeaveMessage(this, groupRecipient);
- try {
- String groupId = getRecipient().getAddress().toGroupString();
- DatabaseFactory.getGroupDatabase(self).setActive(groupId, false);
+ if (threadId != -1 && leaveMessage.isPresent()) {
+ MessageSender.send(this, leaveMessage.get(), threadId, false, null);
- GroupContext context = GroupContext.newBuilder()
- .setId(ByteString.copyFrom(GroupUtil.getDecodedId(groupId)))
- .setType(GroupContext.Type.QUIT)
- .build();
+ GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(this);
+ String groupId = groupRecipient.getAddress().toGroupString();
+ groupDatabase.setActive(groupId, false);
+ groupDatabase.remove(groupId, Address.fromSerialized(TextSecurePreferences.getLocalNumber(this)));
- OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(getRecipient(), context, null, System.currentTimeMillis(), 0, null, Collections.emptyList());
- MessageSender.send(self, outgoingMessage, threadId, false, null);
- DatabaseFactory.getGroupDatabase(self).remove(groupId, Address.fromSerialized(TextSecurePreferences.getLocalNumber(self)));
initializeEnabledCheck();
- } catch (IOException e) {
- Log.w(TAG, e);
- Toast.makeText(self, R.string.ConversationActivity_error_leaving_group, Toast.LENGTH_LONG).show();
+ } else {
+ Toast.makeText(this, R.string.ConversationActivity_error_leaving_group, Toast.LENGTH_LONG).show();
}
});
diff --git a/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java b/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java
index 3ea79f1b4..f5b50ce0f 100644
--- a/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java
+++ b/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java
@@ -3,7 +3,6 @@ package org.thoughtcrime.securesms;
import android.annotation.SuppressLint;
import android.content.ActivityNotFoundException;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
@@ -30,6 +29,7 @@ import android.support.v7.widget.Toolbar;
import android.telephony.PhoneNumberUtils;
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
+import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.logging.Log;
import android.util.Pair;
import android.view.MenuItem;
@@ -37,6 +37,7 @@ import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
+import android.widget.Toast;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
@@ -55,6 +56,7 @@ import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob;
import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.GlideRequests;
+import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.preferences.CorrectedPreferenceFragment;
@@ -62,11 +64,13 @@ import org.thoughtcrime.securesms.preferences.widgets.ColorPickerPreference;
import org.thoughtcrime.securesms.preferences.widgets.ContactPreference;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
+import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.util.CommunicationActions;
import org.thoughtcrime.securesms.util.Dialogs;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
import org.thoughtcrime.securesms.util.DynamicTheme;
+import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.IdentityUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
@@ -378,10 +382,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
if (recipient.isGroupRecipient()) {
if (colorPreference != null) colorPreference.setVisible(false);
- if (blockPreference != null) blockPreference.setVisible(false);
if (identityPreference != null) identityPreference.setVisible(false);
- if (privacyCategory != null) privacyCategory.setVisible(false);
- if (divider != null) divider.setVisible(false);
if (aboutCategory != null) getPreferenceScreen().removePreference(aboutCategory);
if (aboutDivider != null) getPreferenceScreen().removePreference(aboutDivider);
} else {
@@ -659,31 +660,55 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
}
private void handleBlock() {
- new AlertDialog.Builder(getActivity())
- .setTitle(R.string.RecipientPreferenceActivity_block_this_contact_question)
- .setMessage(R.string.RecipientPreferenceActivity_you_will_no_longer_receive_messages_and_calls_from_this_contact)
- .setCancelable(true)
- .setNegativeButton(android.R.string.cancel, null)
- .setPositiveButton(R.string.RecipientPreferenceActivity_block, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- setBlocked(recipient, true);
+ new AsyncTask>() {
+
+ @Override
+ protected Pair doInBackground(Void... voids) {
+ int titleRes = R.string.RecipientPreferenceActivity_block_this_contact_question;
+ int bodyRes = R.string.RecipientPreferenceActivity_you_will_no_longer_receive_messages_and_calls_from_this_contact;
+
+ if (recipient.isGroupRecipient()) {
+ bodyRes = R.string.RecipientPreferenceActivity_block_and_leave_group_description;
+
+ if (recipient.isGroupRecipient() && DatabaseFactory.getGroupDatabase(getContext()).isActive(recipient.getAddress().toGroupString())) {
+ titleRes = R.string.RecipientPreferenceActivity_block_and_leave_group;
+ } else {
+ titleRes = R.string.RecipientPreferenceActivity_block_group;
}
- }).show();
+ }
+
+ return new Pair<>(titleRes, bodyRes);
+ }
+
+ @Override
+ protected void onPostExecute(Pair titleAndBody) {
+ new AlertDialog.Builder(getActivity())
+ .setTitle(titleAndBody.first)
+ .setMessage(titleAndBody.second)
+ .setCancelable(true)
+ .setNegativeButton(android.R.string.cancel, null)
+ .setPositiveButton(R.string.RecipientPreferenceActivity_block, (dialog, which) -> {
+ setBlocked(recipient, true);
+ }).show();
+ }
+ }.execute();
}
private void handleUnblock() {
+ int titleRes = R.string.RecipientPreferenceActivity_unblock_this_contact_question;
+ int bodyRes = R.string.RecipientPreferenceActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact;
+
+ if (recipient.isGroupRecipient()) {
+ titleRes = R.string.RecipientPreferenceActivity_unblock_this_group_question;
+ bodyRes = R.string.RecipientPreferenceActivity_unblock_this_group_description;
+ }
+
new AlertDialog.Builder(getActivity())
- .setTitle(R.string.RecipientPreferenceActivity_unblock_this_contact_question)
- .setMessage(R.string.RecipientPreferenceActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact)
- .setCancelable(true)
- .setNegativeButton(android.R.string.cancel, null)
- .setPositiveButton(R.string.RecipientPreferenceActivity_unblock, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- setBlocked(recipient, false);
- }
- }).show();
+ .setTitle(titleRes)
+ .setMessage(bodyRes)
+ .setCancelable(true)
+ .setNegativeButton(android.R.string.cancel, null)
+ .setPositiveButton(R.string.RecipientPreferenceActivity_unblock, (dialog, which) -> setBlocked(recipient, false)).show();
}
private void setBlocked(final Recipient recipient, final boolean blocked) {
@@ -695,6 +720,23 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
DatabaseFactory.getRecipientDatabase(context)
.setBlocked(recipient, blocked);
+ if (recipient.isGroupRecipient() && DatabaseFactory.getGroupDatabase(context).isActive(recipient.getAddress().toGroupString())) {
+ long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
+ Optional leaveMessage = GroupUtil.createGroupLeaveMessage(context, recipient);
+
+ if (threadId != -1 && leaveMessage.isPresent()) {
+ MessageSender.send(context, leaveMessage.get(), threadId, false, null);
+
+ GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
+ String groupId = recipient.getAddress().toGroupString();
+ groupDatabase.setActive(groupId, false);
+ groupDatabase.remove(groupId, Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
+ } else {
+ Log.w(TAG, "Failed to leave group. Can't block.");
+ Toast.makeText(context, R.string.RecipientPreferenceActivity_error_leaving_group, Toast.LENGTH_LONG).show();
+ }
+ }
+
ApplicationContext.getInstance(context)
.getJobManager()
.add(new MultiDeviceBlockedUpdateJob(context));
diff --git a/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java b/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java
index e68126c6c..a4faa115e 100644
--- a/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java
+++ b/src/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java
@@ -44,6 +44,9 @@ import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.util.CredentialsProvider;
+import org.whispersystems.signalservice.api.util.RealtimeSleepTimer;
+import org.whispersystems.signalservice.api.util.SleepTimer;
+import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
import org.whispersystems.signalservice.api.websocket.ConnectivityListener;
import dagger.Module;
@@ -124,10 +127,13 @@ public class SignalCommunicationModule {
@Provides
synchronized SignalServiceMessageReceiver provideSignalMessageReceiver() {
if (this.messageReceiver == null) {
+ SleepTimer sleepTimer = TextSecurePreferences.isGcmDisabled(context) ? new RealtimeSleepTimer(context) : new UptimeSleepTimer();
+
this.messageReceiver = new SignalServiceMessageReceiver(networkAccess.getConfiguration(context),
new DynamicCredentialsProvider(context),
BuildConfig.USER_AGENT,
- new PipeConnectivityListener());
+ new PipeConnectivityListener(),
+ sleepTimer);
}
return this.messageReceiver;
diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java
index 8e79ca9f4..93a1e8ca4 100644
--- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java
@@ -11,6 +11,7 @@ import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement;
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
import org.thoughtcrime.securesms.recipients.Recipient;
+import org.thoughtcrime.securesms.util.GroupUtil;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
import org.whispersystems.signalservice.api.messages.multidevice.BlockedListMessage;
@@ -47,17 +48,20 @@ public class MultiDeviceBlockedUpdateJob extends MasterSecretJob implements Inje
RecipientDatabase database = DatabaseFactory.getRecipientDatabase(context);
try (RecipientReader reader = database.readerForBlocked(database.getBlocked())) {
- List blocked = new LinkedList<>();
+ List blockedIndividuals = new LinkedList<>();
+ List blockedGroups = new LinkedList<>();
Recipient recipient;
while ((recipient = reader.getNext()) != null) {
- if (!recipient.isGroupRecipient()) {
- blocked.add(recipient.getAddress().serialize());
+ if (recipient.isGroupRecipient()) {
+ blockedGroups.add(GroupUtil.getDecodedId(recipient.getAddress().toGroupString()));
+ } else {
+ blockedIndividuals.add(recipient.getAddress().serialize());
}
}
- messageSender.sendMessage(SignalServiceSyncMessage.forBlocked(new BlockedListMessage(blocked)));
+ messageSender.sendMessage(SignalServiceSyncMessage.forBlocked(new BlockedListMessage(blockedIndividuals, blockedGroups)));
}
}
diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java
index 460443fe8..3d1119b0f 100644
--- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java
@@ -75,7 +75,9 @@ public class MultiDeviceGroupUpdateJob extends MasterSecretJob implements Inject
out.write(new DeviceGroup(record.getId(), Optional.fromNullable(record.getTitle()),
members, getAvatar(record.getAvatar()),
- record.isActive(), expirationTimer));
+ record.isActive(), expirationTimer,
+ Optional.of(recipient.getColor().serialize()),
+ recipient.isBlocked()));
}
}
diff --git a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
index 9bc277f37..bdc9e89a0 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
@@ -175,6 +175,11 @@ public class PushDecryptJob extends ContextJob {
SignalServiceContent content = cipher.decrypt(envelope);
+ if (shouldIgnore(envelope, content)) {
+ Log.i(TAG, "Ignoring message.");
+ return;
+ }
+
if (content.getDataMessage().isPresent()) {
SignalServiceDataMessage message = content.getDataMessage().get();
boolean isMediaMessage = message.getAttachments().isPresent() || message.getQuote().isPresent() || message.getSharedContacts().isPresent();
@@ -941,4 +946,36 @@ public class PushDecryptJob extends ContextJob {
return Recipient.from(context, Address.fromExternal(context, envelope.getSource()), false);
}
}
+
+ private boolean shouldIgnore(@NonNull SignalServiceEnvelope envelope, @NonNull SignalServiceContent content) {
+ Recipient sender = Recipient.from(context, Address.fromExternal(context, envelope.getSource()), false);
+
+ if (content.getDataMessage().isPresent()) {
+ SignalServiceDataMessage message = content.getDataMessage().get();
+ Recipient conversation = getMessageDestination(envelope, message);
+
+ if (conversation.isGroupRecipient() && conversation.isBlocked()) {
+ return true;
+ } else if (conversation.isGroupRecipient()) {
+ GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
+ Optional groupId = message.getGroupInfo().isPresent() ? Optional.of(GroupUtil.getEncodedId(message.getGroupInfo().get().getGroupId(), false))
+ : Optional.absent();
+
+ boolean isTextMessage = message.getBody().isPresent();
+ boolean isMediaMessage = message.getAttachments().isPresent() || message.getQuote().isPresent() || message.getSharedContacts().isPresent();
+ boolean isExpireMessage = message.isExpirationUpdate();
+ boolean isContentMessage = !message.isGroupUpdate() && (isTextMessage || isMediaMessage || isExpireMessage);
+ boolean isGroupActive = groupId.isPresent() && groupDatabase.isActive(groupId.get());
+ boolean isLeaveMessage = message.getGroupInfo().isPresent() && message.getGroupInfo().get().getType() == SignalServiceGroup.Type.QUIT;
+
+ return (isContentMessage && !isGroupActive) || (sender.isBlocked() && !isLeaveMessage);
+ } else {
+ return sender.isBlocked();
+ }
+ } else if (content.getCallMessage().isPresent()) {
+ return sender.isBlocked();
+ }
+
+ return false;
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java b/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java
index fa73592bf..924f93f12 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java
@@ -34,22 +34,17 @@ public abstract class PushReceivedJob extends ContextJob {
if (envelope.isReceipt()) {
handleReceipt(envelope);
} else if (envelope.isPreKeySignalMessage() || envelope.isSignalMessage()) {
- handleMessage(envelope, source);
+ handleMessage(envelope);
} else {
Log.w(TAG, "Received envelope of unknown type: " + envelope.getType());
}
}
- private void handleMessage(SignalServiceEnvelope envelope, Address source) {
- Recipient recipients = Recipient.from(context, source, false);
- JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
-
- if (!recipients.isBlocked()) {
- long messageId = DatabaseFactory.getPushDatabase(context).insert(envelope);
- jobManager.add(new PushDecryptJob(context, messageId));
- } else {
- Log.w(TAG, "*** Received blocked push message, ignoring...");
- }
+ private void handleMessage(SignalServiceEnvelope envelope) {
+ long messageId = DatabaseFactory.getPushDatabase(context).insert(envelope);
+ ApplicationContext.getInstance(context)
+ .getJobManager()
+ .add(new PushDecryptJob(context, messageId));
}
private void handleReceipt(SignalServiceEnvelope envelope) {
diff --git a/src/org/thoughtcrime/securesms/util/GroupUtil.java b/src/org/thoughtcrime/securesms/util/GroupUtil.java
index 0d3ebf741..857a35eb2 100644
--- a/src/org/thoughtcrime/securesms/util/GroupUtil.java
+++ b/src/org/thoughtcrime/securesms/util/GroupUtil.java
@@ -3,14 +3,23 @@ package org.thoughtcrime.securesms.util;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.support.annotation.WorkerThread;
+
+import com.google.protobuf.ByteString;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.Address;
+import org.thoughtcrime.securesms.database.DatabaseFactory;
+import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.logging.Log;
+import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
+import org.thoughtcrime.securesms.sms.MessageSender;
+import org.whispersystems.libsignal.util.guava.Optional;
import java.io.IOException;
+import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@@ -20,7 +29,7 @@ public class GroupUtil {
private static final String ENCODED_SIGNAL_GROUP_PREFIX = "__textsecure_group__!";
private static final String ENCODED_MMS_GROUP_PREFIX = "__signal_mms_group__!";
- private static final String TAG = GroupUtil.class.getSimpleName();
+ private static final String TAG = GroupUtil.class.getSimpleName();
public static String getEncodedId(byte[] groupId, boolean mms) {
return (mms ? ENCODED_MMS_GROUP_PREFIX : ENCODED_SIGNAL_GROUP_PREFIX) + Hex.toStringCondensed(groupId);
@@ -42,6 +51,33 @@ public class GroupUtil {
return groupId.startsWith(ENCODED_MMS_GROUP_PREFIX);
}
+ @WorkerThread
+ public static Optional createGroupLeaveMessage(@NonNull Context context, @NonNull Recipient groupRecipient) {
+ String encodedGroupId = groupRecipient.getAddress().toGroupString();
+ GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
+
+ if (!groupDatabase.isActive(encodedGroupId)) {
+ Log.w(TAG, "Group has already been left.");
+ return Optional.absent();
+ }
+
+ ByteString decodedGroupId;
+ try {
+ decodedGroupId = ByteString.copyFrom(getDecodedId(encodedGroupId));
+ } catch (IOException e) {
+ Log.w(TAG, "Failed to decode group ID.", e);
+ return Optional.absent();
+ }
+
+ GroupContext groupContext = GroupContext.newBuilder()
+ .setId(decodedGroupId)
+ .setType(GroupContext.Type.QUIT)
+ .build();
+
+ return Optional.of(new OutgoingGroupMediaMessage(groupRecipient, groupContext, null, System.currentTimeMillis(), 0, null, Collections.emptyList()));
+ }
+
+
public static @NonNull GroupDescription getDescription(@NonNull Context context, @Nullable String encodedGroup) {
if (encodedGroup == null) {
return new GroupDescription(context, null);