Handle 428 rate limiting.

This commit is contained in:
Greyson Parrelli
2021-05-05 12:49:18 -04:00
parent 02d060ca0a
commit 31e1c6f7aa
60 changed files with 1235 additions and 57 deletions

View File

@@ -228,6 +228,8 @@ import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.profiles.spoofing.ReviewBannerView;
import org.thoughtcrime.securesms.profiles.spoofing.ReviewCardDialogFragment;
import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.ratelimit.RecaptchaProofActivity;
import org.thoughtcrime.securesms.ratelimit.RecaptchaProofBottomSheetFragment;
import org.thoughtcrime.securesms.reactions.ReactionsBottomSheetDialogFragment;
import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiBottomSheetDialogFragment;
import org.thoughtcrime.securesms.recipients.LiveRecipient;
@@ -579,6 +581,10 @@ public class ConversationActivity extends PassphraseRequiredActivity
setVisibleThread(threadId);
ConversationUtil.refreshRecipientShortcuts();
if (SignalStore.rateLimit().needsRecaptcha()) {
RecaptchaProofBottomSheetFragment.show(getSupportFragmentManager());
}
}
@Override
@@ -2200,6 +2206,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
this.viewModel.setArgs(args);
this.viewModel.getWallpaper().observe(this, this::updateWallpaper);
this.viewModel.getEvents().observe(this, this::onViewModelEvent);
}
private void initializeGroupViewModel() {
@@ -2973,6 +2980,14 @@ public class ConversationActivity extends PassphraseRequiredActivity
}
}
private void onViewModelEvent(@NonNull ConversationViewModel.Event event) {
if (event == ConversationViewModel.Event.SHOW_RECAPTCHA) {
RecaptchaProofBottomSheetFragment.show(getSupportFragmentManager());
} else {
throw new AssertionError("Unexpected event!");
}
}
private void updateLinkPreviewState() {
if (SignalStore.settings().isLinkPreviewsEnabled() && isSecureText && !sendButton.getSelectedTransport().isSms() && !attachmentManager.isAttachmentPresent()) {
linkPreviewViewModel.onEnabled();

View File

@@ -124,6 +124,7 @@ import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter;
import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.ratelimit.RecaptchaProofBottomSheetFragment;
import org.thoughtcrime.securesms.reactions.ReactionsBottomSheetDialogFragment;
import org.thoughtcrime.securesms.recipients.LiveRecipient;
import org.thoughtcrime.securesms.recipients.Recipient;
@@ -1503,6 +1504,11 @@ public class ConversationFragment extends LoggingFragment {
listener.onMessageWithErrorClicked(messageRecord);
}
@Override
public void onMessageWithRecaptchaNeededClicked(@NonNull MessageRecord messageRecord) {
RecaptchaProofBottomSheetFragment.show(getChildFragmentManager());
}
@Override
public void onVoiceNotePause(@NonNull Uri uri) {
voiceNoteMediaController.pausePlayback(uri);

View File

@@ -97,6 +97,7 @@ import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob;
import org.thoughtcrime.securesms.jobs.MmsDownloadJob;
import org.thoughtcrime.securesms.jobs.MmsSendJob;
import org.thoughtcrime.securesms.jobs.SmsSendJob;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
import org.thoughtcrime.securesms.mms.GlideRequests;
@@ -1054,6 +1055,8 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
alertView.setFailed();
} else if (messageRecord.isPendingInsecureSmsFallback()) {
alertView.setPendingApproval();
} else if (messageRecord.isRateLimited()) {
alertView.setRateLimited();
} else {
alertView.setNone();
}
@@ -1166,7 +1169,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
boolean differentTimestamps = next.isPresent() && !DateUtils.isSameExtendedRelativeTimestamp(context, locale, next.get().getTimestamp(), current.getTimestamp());
if (forceFooter(messageRecord) || current.getExpiresIn() > 0 || !current.isSecure() || current.isPending() || current.isPendingInsecureSmsFallback() ||
current.isFailed() || differentTimestamps || isEndOfMessageCluster(current, next, isGroupThread))
current.isFailed() || current.isRateLimited() || differentTimestamps || isEndOfMessageCluster(current, next, isGroupThread))
{
ConversationItemFooter activeFooter = getActiveFooter(current);
activeFooter.setVisibility(VISIBLE);
@@ -1211,10 +1214,11 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
}
private boolean shouldInterceptClicks(MessageRecord messageRecord) {
return batchSelected.isEmpty() &&
((messageRecord.isFailed() && !messageRecord.isMmsNotification()) ||
messageRecord.isPendingInsecureSmsFallback() ||
messageRecord.isBundleKeyExchange());
return batchSelected.isEmpty() &&
((messageRecord.isFailed() && !messageRecord.isMmsNotification()) ||
(messageRecord.isRateLimited() && SignalStore.rateLimit().needsRecaptcha()) ||
messageRecord.isPendingInsecureSmsFallback() ||
messageRecord.isBundleKeyExchange());
}
@SuppressLint("SetTextI18n")
@@ -1682,6 +1686,10 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
if (eventListener != null) {
eventListener.onMessageWithErrorClicked(messageRecord);
}
} else if (messageRecord.isRateLimited() && SignalStore.rateLimit().needsRecaptcha()) {
if (eventListener != null) {
eventListener.onMessageWithRecaptchaNeededClicked(messageRecord);
}
} else if (!messageRecord.isOutgoing() && messageRecord.isIdentityMismatchFailure()) {
handleApproveIdentity();
} else if (messageRecord.isPendingInsecureSmsFallback()) {

View File

@@ -10,6 +10,9 @@ import androidx.lifecycle.Transformations;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.signal.core.util.logging.Log;
import org.signal.paging.PagedData;
import org.signal.paging.PagingConfig;
@@ -19,8 +22,10 @@ import org.thoughtcrime.securesms.database.DatabaseObserver;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.mediasend.Media;
import org.thoughtcrime.securesms.mediasend.MediaRepository;
import org.thoughtcrime.securesms.ratelimit.RecaptchaRequiredEvent;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.SingleLiveEvent;
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper;
import org.whispersystems.libsignal.util.Pair;
@@ -28,7 +33,7 @@ import org.whispersystems.libsignal.util.Pair;
import java.util.List;
import java.util.Objects;
class ConversationViewModel extends ViewModel {
public class ConversationViewModel extends ViewModel {
private static final String TAG = Log.tag(ConversationViewModel.class);
@@ -46,6 +51,7 @@ class ConversationViewModel extends ViewModel {
private final DatabaseObserver.Observer messageObserver;
private final MutableLiveData<RecipientId> recipientId;
private final LiveData<ChatWallpaper> wallpaper;
private final SingleLiveEvent<Event> events;
private ConversationIntents.Args args;
private int jumpToPosition;
@@ -59,6 +65,7 @@ class ConversationViewModel extends ViewModel {
this.showScrollButtons = new MutableLiveData<>(false);
this.hasUnreadMentions = new MutableLiveData<>(false);
this.recipientId = new MutableLiveData<>();
this.events = new SingleLiveEvent<>();
this.pagingController = new ProxyPagingController();
this.messageObserver = pagingController::onDataInvalidated;
@@ -108,6 +115,8 @@ class ConversationViewModel extends ViewModel {
wallpaper = Transformations.distinctUntilChanged(Transformations.map(Transformations.switchMap(recipientId,
id -> Recipient.live(id).getLiveData()),
Recipient::getWallpaper));
EventBus.getDefault().register(this);
}
void onAttachmentKeyboardOpen() {
@@ -144,6 +153,10 @@ class ConversationViewModel extends ViewModel {
return wallpaper;
}
@NonNull LiveData<Event> getEvents() {
return events;
}
void setHasUnreadMentions(boolean hasUnreadMentions) {
this.hasUnreadMentions.setValue(hasUnreadMentions);
}
@@ -184,10 +197,20 @@ class ConversationViewModel extends ViewModel {
return Objects.requireNonNull(args);
}
@Subscribe(threadMode = ThreadMode.POSTING)
public void onRecaptchaRequiredEvent(@NonNull RecaptchaRequiredEvent event) {
events.postValue(Event.SHOW_RECAPTCHA);
}
@Override
protected void onCleared() {
super.onCleared();
ApplicationDependencies.getDatabaseObserver().unregisterObserver(messageObserver);
EventBus.getDefault().unregister(this);
}
enum Event {
SHOW_RECAPTCHA
}
static class Factory extends ViewModelProvider.NewInstanceFactory {