Show dialog if another device registered with same number

This commit is contained in:
Moxie Marlinspike
2017-11-15 16:29:00 -08:00
parent 909c0c544c
commit e37c06c563
11 changed files with 139 additions and 40 deletions

View File

@@ -90,8 +90,10 @@ import org.thoughtcrime.securesms.components.identity.UntrustedSendDialog;
import org.thoughtcrime.securesms.components.identity.UnverifiedBannerView;
import org.thoughtcrime.securesms.components.identity.UnverifiedSendDialog;
import org.thoughtcrime.securesms.components.location.SignalPlace;
import org.thoughtcrime.securesms.components.reminder.ExpiredBuildReminder;
import org.thoughtcrime.securesms.components.reminder.InviteReminder;
import org.thoughtcrime.securesms.components.reminder.ReminderView;
import org.thoughtcrime.securesms.components.reminder.UnauthorizedReminder;
import org.thoughtcrime.securesms.contacts.ContactAccessor;
import org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData;
import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable;
@@ -113,6 +115,7 @@ import org.thoughtcrime.securesms.database.RecipientDatabase.RegisteredState;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.identity.IdentityRecordList;
import org.thoughtcrime.securesms.events.ReminderUpdateEvent;
import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob;
import org.thoughtcrime.securesms.jobs.RetrieveProfileJob;
import org.thoughtcrime.securesms.mms.AttachmentManager;
@@ -567,6 +570,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
inputPanel.onKeyboardShown();
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(ReminderUpdateEvent event) {
updateReminders(recipient.hasSeenInviteReminder());
}
//////// Event Handlers
private void handleReturnToConversationList() {
@@ -1079,25 +1087,27 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private void onSecurityUpdated() {
Log.w(TAG, "onSecurityUpdated()");
updateInviteReminder(recipient.hasSeenInviteReminder());
updateReminders(recipient.hasSeenInviteReminder());
updateDefaultSubscriptionId(recipient.getDefaultSubscriptionId());
}
protected void updateInviteReminder(boolean seenInvite) {
Log.w(TAG, "updateInviteReminder(" + seenInvite+")");
if (TextSecurePreferences.isPushRegistered(this) &&
TextSecurePreferences.isShowInviteReminders(this) &&
!isSecureText &&
!seenInvite &&
!recipient.isGroupRecipient())
protected void updateReminders(boolean seenInvite) {
Log.w(TAG, "updateReminders(" + seenInvite+")");
if (UnauthorizedReminder.isEligible(this)) {
reminderView.get().showReminder(new UnauthorizedReminder(this));
} else if (ExpiredBuildReminder.isEligible()) {
reminderView.get().showReminder(new ExpiredBuildReminder(this));
} else if (TextSecurePreferences.isPushRegistered(this) &&
TextSecurePreferences.isShowInviteReminders(this) &&
!isSecureText &&
!seenInvite &&
!recipient.isGroupRecipient())
{
InviteReminder reminder = new InviteReminder(this, recipient);
reminder.setOkListener(new OnClickListener() {
@Override
public void onClick(View v) {
handleInviteLink();
reminderView.get().requestDismiss();
}
reminder.setOkListener(v -> {
handleInviteLink();
reminderView.get().requestDismiss();
});
reminderView.get().showReminder(reminder);
} else if (reminderView.resolved()) {
@@ -1302,7 +1312,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
setBlockedUserState(recipient, isSecureText, isDefaultSms);
setActionBarColor(recipient.getColor());
setGroupShareProfileReminder(recipient);
updateInviteReminder(recipient.hasSeenInviteReminder());
updateReminders(recipient.hasSeenInviteReminder());
updateDefaultSubscriptionId(recipient.getDefaultSubscriptionId());
initializeSecurity(isSecureText, isDefaultSms);
invalidateOptionsMenu();

View File

@@ -16,6 +16,7 @@
*/
package org.thoughtcrime.securesms;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
@@ -42,7 +43,6 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.animation.Animation;
@@ -53,7 +53,6 @@ import android.widget.Toast;
import org.thoughtcrime.securesms.ConversationAdapter.HeaderViewHolder;
import org.thoughtcrime.securesms.ConversationAdapter.ItemClickListener;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
import org.thoughtcrime.securesms.database.RecipientDatabase;
@@ -80,6 +79,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Set;
@SuppressLint("StaticFieldLeak")
public class ConversationFragment extends Fragment
implements LoaderManager.LoaderCallbacks<Cursor>
{

View File

@@ -52,6 +52,9 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.thoughtcrime.securesms.ConversationListAdapter.ItemClickListener;
import org.thoughtcrime.securesms.components.recyclerview.DeleteItemAnimator;
import org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton;
@@ -64,10 +67,12 @@ import org.thoughtcrime.securesms.components.reminder.Reminder;
import org.thoughtcrime.securesms.components.reminder.ReminderView;
import org.thoughtcrime.securesms.components.reminder.ShareReminder;
import org.thoughtcrime.securesms.components.reminder.SystemSmsImportReminder;
import org.thoughtcrime.securesms.components.reminder.UnauthorizedReminder;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
import org.thoughtcrime.securesms.database.loaders.ConversationListLoader;
import org.thoughtcrime.securesms.events.ReminderUpdateEvent;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
@@ -121,7 +126,7 @@ public class ConversationListFragment extends Fragment
if (archive) fab.setVisibility(View.GONE);
else fab.setVisibility(View.VISIBLE);
reminderView.setOnDismissListener(this::updateReminders);
reminderView.setOnDismissListener(() -> updateReminders(true));
list.setHasFixedSize(true);
list.setLayoutManager(new LinearLayoutManager(getActivity()));
@@ -146,8 +151,9 @@ public class ConversationListFragment extends Fragment
public void onResume() {
super.onResume();
updateReminders();
updateReminders(true);
list.getAdapter().notifyDataSetChanged();
EventBus.getDefault().register(this);
}
@Override
@@ -155,6 +161,7 @@ public class ConversationListFragment extends Fragment
super.onPause();
fab.stopPulse();
EventBus.getDefault().unregister(this);
}
public ConversationListAdapter getListAdapter() {
@@ -173,12 +180,14 @@ public class ConversationListFragment extends Fragment
}
@SuppressLint("StaticFieldLeak")
private void updateReminders() {
reminderView.hide();
private void updateReminders(boolean hide) {
new AsyncTask<Context, Void, Optional<? extends Reminder>>() {
@Override protected Optional<? extends Reminder> doInBackground(Context... params) {
@Override
protected Optional<? extends Reminder> doInBackground(Context... params) {
final Context context = params[0];
if (ExpiredBuildReminder.isEligible()) {
if (UnauthorizedReminder.isEligible(context)) {
return Optional.of(new UnauthorizedReminder(context));
} else if (ExpiredBuildReminder.isEligible()) {
return Optional.of(new ExpiredBuildReminder(context));
} else if (OutdatedBuildReminder.isEligible()) {
return Optional.of(new OutdatedBuildReminder(context));
@@ -197,9 +206,12 @@ public class ConversationListFragment extends Fragment
}
}
@Override protected void onPostExecute(Optional<? extends Reminder> reminder) {
@Override
protected void onPostExecute(Optional<? extends Reminder> reminder) {
if (reminder.isPresent() && getActivity() != null && !isRemoving()) {
reminderView.showReminder(reminder.get());
} else if (!reminder.isPresent()) {
reminderView.hide();
}
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, getActivity());
@@ -436,6 +448,11 @@ public class ConversationListFragment extends Fragment
actionMode = null;
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(ReminderUpdateEvent event) {
updateReminders(false);
}
private class ArchiveListenerCallback extends ItemTouchHelper.SimpleCallback {
ArchiveListenerCallback() {

View File

@@ -121,7 +121,7 @@ public class ConversationPopupActivity extends ConversationActivity {
}
@Override
protected void updateInviteReminder(boolean seenInvite) {
protected void updateReminders(boolean seenInvite) {
if (reminderView.resolved()) {
reminderView.get().setVisibility(View.GONE);
}

View File

@@ -373,6 +373,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif
TextSecurePreferences.setSignalingKey(RegistrationActivity.this, signalingKey);
TextSecurePreferences.setSignedPreKeyRegistered(RegistrationActivity.this, true);
TextSecurePreferences.setPromptedPushRegistration(RegistrationActivity.this, true);
TextSecurePreferences.setUnauthorizedReceived(RegistrationActivity.this, false);
return true;
} catch (IOException e) {

View File

@@ -3,25 +3,22 @@ package org.thoughtcrime.securesms.components.reminder;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.view.View;
import android.view.View.OnClickListener;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.Util;
public class ExpiredBuildReminder extends Reminder {
@SuppressWarnings("unused")
private static final String TAG = ExpiredBuildReminder.class.getSimpleName();
public ExpiredBuildReminder(final Context context) {
super(context.getString(R.string.reminder_header_expired_build),
context.getString(R.string.reminder_header_expired_build_details));
setOkListener(new OnClickListener() {
@Override public void onClick(View v) {
try {
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + context.getPackageName())));
} catch (android.content.ActivityNotFoundException anfe) {
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + context.getPackageName())));
}
setOkListener(v -> {
try {
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + context.getPackageName())));
} catch (android.content.ActivityNotFoundException anfe) {
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + context.getPackageName())));
}
});
}

View File

@@ -0,0 +1,27 @@
package org.thoughtcrime.securesms.components.reminder;
import android.content.Context;
import android.content.Intent;
import org.thoughtcrime.securesms.RegistrationActivity;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
public class UnauthorizedReminder extends Reminder {
public UnauthorizedReminder(final Context context) {
super("Device no longer registered",
"This is likely because you registered your phone number with Signal on a different device. Tap to re-register.");
setOkListener(v -> context.startActivity(new Intent(context, RegistrationActivity.class)));
}
@Override
public boolean isDismissable() {
return false;
}
public static boolean isEligible(Context context) {
return TextSecurePreferences.isUnauthorizedRecieved(context);
}
}

View File

@@ -1,11 +1,14 @@
package org.thoughtcrime.securesms.dependencies;
import android.content.Context;
import android.util.Log;
import org.greenrobot.eventbus.EventBus;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.CreateProfileActivity;
import org.thoughtcrime.securesms.DeviceListFragment;
import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl;
import org.thoughtcrime.securesms.events.ReminderUpdateEvent;
import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob;
import org.thoughtcrime.securesms.jobs.AvatarDownloadJob;
import org.thoughtcrime.securesms.jobs.CleanPreKeysJob;
@@ -40,6 +43,7 @@ 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.websocket.ConnectivityListener;
import dagger.Module;
import dagger.Provides;
@@ -74,6 +78,8 @@ import dagger.Provides;
MultiDeviceReadReceiptUpdateJob.class})
public class SignalCommunicationModule {
private static final String TAG = SignalCommunicationModule.class.getSimpleName();
private final Context context;
private final SignalServiceNetworkAccess networkAccess;
@@ -118,7 +124,8 @@ public class SignalCommunicationModule {
if (this.messageReceiver == null) {
this.messageReceiver = new SignalServiceMessageReceiver(networkAccess.getConfiguration(context),
new DynamicCredentialsProvider(context),
BuildConfig.USER_AGENT);
BuildConfig.USER_AGENT,
new PipeConnectivityListener());
}
return this.messageReceiver;
@@ -148,4 +155,30 @@ public class SignalCommunicationModule {
}
}
private class PipeConnectivityListener implements ConnectivityListener {
@Override
public void onConnected() {
Log.w(TAG, "onConnected()");
}
@Override
public void onConnecting() {
Log.w(TAG, "onConnecting()");
}
@Override
public void onDisconnected() {
Log.w(TAG, "onDisconnected()");
}
@Override
public void onAuthenticationFailure() {
Log.w(TAG, "onAuthenticationFailure()");
TextSecurePreferences.setUnauthorizedReceived(context, true);
EventBus.getDefault().post(new ReminderUpdateEvent());
}
}
}

View File

@@ -0,0 +1,5 @@
package org.thoughtcrime.securesms.events;
public class ReminderUpdateEvent {
}

View File

@@ -115,6 +115,15 @@ public class TextSecurePreferences {
private static final String PROFILE_AVATAR_ID_PREF = "pref_profile_avatar_id";
public static final String READ_RECEIPTS_PREF = "pref_read_receipts";
public static final String INCOGNITO_KEYBORAD_PREF = "pref_incognito_keyboard";
private static final String UNAUTHORIZED_RECEIVED = "pref_unauthorized_received";
public static void setUnauthorizedReceived(Context context, boolean value) {
setBooleanPreference(context, UNAUTHORIZED_RECEIVED, value);
}
public static boolean isUnauthorizedRecieved(Context context) {
return getBooleanPreference(context, UNAUTHORIZED_RECEIVED, false);
}
public static boolean isIncognitoKeyboardEnabled(Context context) {
return getBooleanPreference(context, INCOGNITO_KEYBORAD_PREF, false);