diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 819179fb66..9fdb84a489 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -615,11 +615,6 @@ - - - - - diff --git a/src/org/thoughtcrime/securesms/ApplicationContext.java b/src/org/thoughtcrime/securesms/ApplicationContext.java index ccef1114d2..3bf81018ac 100644 --- a/src/org/thoughtcrime/securesms/ApplicationContext.java +++ b/src/org/thoughtcrime/securesms/ApplicationContext.java @@ -75,7 +75,6 @@ import org.thoughtcrime.securesms.profiles.AvatarHelper; import org.thoughtcrime.securesms.providers.BlobProvider; import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess; import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.service.DirectoryRefreshListener; import org.thoughtcrime.securesms.service.ExpiringMessageManager; import org.thoughtcrime.securesms.service.IncomingMessageObserver; import org.thoughtcrime.securesms.service.KeyCachingService; @@ -353,7 +352,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc private void initializePeriodicTasks() { RotateSignedPreKeyListener.schedule(this); - DirectoryRefreshListener.schedule(this); LocalBackupListener.schedule(this); RotateSenderCertificateListener.schedule(this); BackgroundPollWorker.schedule(this); // Session diff --git a/src/org/thoughtcrime/securesms/ContactSelectionActivity.java b/src/org/thoughtcrime/securesms/ContactSelectionActivity.java index 6b6f7554ef..e408709009 100644 --- a/src/org/thoughtcrime/securesms/ContactSelectionActivity.java +++ b/src/org/thoughtcrime/securesms/ContactSelectionActivity.java @@ -16,24 +16,17 @@ */ package org.thoughtcrime.securesms; -import android.content.Context; -import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.widget.SwipeRefreshLayout; import org.thoughtcrime.securesms.components.ContactFilterToolbar; import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode; -import org.thoughtcrime.securesms.logging.Log; -import org.thoughtcrime.securesms.util.DirectoryHelper; import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme; import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.ViewUtil; -import java.io.IOException; -import java.lang.ref.WeakReference; - import network.loki.messenger.R; /** @@ -109,44 +102,11 @@ public abstract class ContactSelectionActivity extends PassphraseRequiredActionB } @Override - public void onRefresh() { - new RefreshDirectoryTask(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, getApplicationContext()); - } + public void onRefresh() { } @Override public void onContactSelected(String number) {} @Override public void onContactDeselected(String number) {} - - private static class RefreshDirectoryTask extends AsyncTask { - - private final WeakReference activity; - - private RefreshDirectoryTask(ContactSelectionActivity activity) { - this.activity = new WeakReference<>(activity); - } - - @Override - protected Void doInBackground(Context... params) { - - try { - DirectoryHelper.refreshDirectory(params[0], true); - } catch (IOException e) { - Log.w(TAG, e); - } - - return null; - } - - @Override - protected void onPostExecute(Void result) { - ContactSelectionActivity activity = this.activity.get(); - - if (activity != null && !activity.isFinishing()) { - activity.toolbar.clear(); - activity.contactsFragment.resetQueryFilter(); - } - } - } } diff --git a/src/org/thoughtcrime/securesms/ContactSelectionListFragment.java b/src/org/thoughtcrime/securesms/ContactSelectionListFragment.java index c4878b861c..c95359516f 100644 --- a/src/org/thoughtcrime/securesms/ContactSelectionListFragment.java +++ b/src/org/thoughtcrime/securesms/ContactSelectionListFragment.java @@ -17,7 +17,6 @@ package org.thoughtcrime.securesms; -import android.Manifest; import android.annotation.SuppressLint; import android.database.Cursor; import android.os.AsyncTask; @@ -44,14 +43,11 @@ import org.thoughtcrime.securesms.contacts.ContactSelectionListItem; import org.thoughtcrime.securesms.contacts.ContactsCursorLoader; import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode; import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter; -import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.permissions.Permissions; -import org.thoughtcrime.securesms.util.DirectoryHelper; import org.thoughtcrime.securesms.util.StickyHeaderDecoration; import org.thoughtcrime.securesms.util.ViewUtil; -import java.io.IOException; import java.util.LinkedList; import java.util.List; import java.util.Set; @@ -259,12 +255,6 @@ public class ContactSelectionListFragment extends Fragment @Override protected Boolean doInBackground(Void... voids) { - try { - DirectoryHelper.refreshDirectory(getContext(), false); - return true; - } catch (IOException e) { - Log.w(TAG, e); - } return false; } diff --git a/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java b/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java index 67b50b639c..ad9bfcb85e 100644 --- a/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java +++ b/src/org/thoughtcrime/securesms/DatabaseUpgradeActivity.java @@ -40,7 +40,6 @@ import org.thoughtcrime.securesms.database.PushDatabase; import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob; import org.thoughtcrime.securesms.jobs.CreateSignedPreKeyJob; -import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob; import org.thoughtcrime.securesms.jobs.PushDecryptJob; import org.thoughtcrime.securesms.jobs.RefreshAttributesJob; import org.thoughtcrime.securesms.logging.Log; @@ -250,12 +249,6 @@ public class DatabaseUpgradeActivity extends BaseActivity { scheduleMessagesInPushDatabase(context);; } - if (params[0] < CONTACTS_ACCOUNT_VERSION) { - ApplicationContext.getInstance(getApplicationContext()) - .getJobManager() - .add(new DirectoryRefreshJob(false)); - } - if (params[0] < MEDIA_DOWNLOAD_CONTROLS_VERSION) { schedulePendingIncomingParts(context); } @@ -264,15 +257,6 @@ public class DatabaseUpgradeActivity extends BaseActivity { ApplicationContext.getInstance(getApplicationContext()) .getJobManager() .add(new RefreshAttributesJob()); - ApplicationContext.getInstance(getApplicationContext()) - .getJobManager() - .add(new DirectoryRefreshJob(false)); - } - - if (params[0] < PROFILES) { - ApplicationContext.getInstance(getApplicationContext()) - .getJobManager() - .add(new DirectoryRefreshJob(false)); } if (params[0] < SCREENSHOTS) { diff --git a/src/org/thoughtcrime/securesms/RegistrationActivity.java b/src/org/thoughtcrime/securesms/RegistrationActivity.java index ff09e7ed93..6f5ba224be 100644 --- a/src/org/thoughtcrime/securesms/RegistrationActivity.java +++ b/src/org/thoughtcrime/securesms/RegistrationActivity.java @@ -49,7 +49,6 @@ import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.IdentityDatabase; import org.thoughtcrime.securesms.database.NoExternalStorageException; -import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob; import org.thoughtcrime.securesms.jobs.RotateCertificateJob; import org.thoughtcrime.securesms.lock.RegistrationLockReminders; import org.thoughtcrime.securesms.logging.Log; @@ -57,7 +56,6 @@ import org.thoughtcrime.securesms.notifications.NotificationChannels; import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.push.AccountManagerFactory; import org.thoughtcrime.securesms.registration.CaptchaActivity; -import org.thoughtcrime.securesms.service.DirectoryRefreshListener; import org.thoughtcrime.securesms.service.RotateSignedPreKeyListener; import org.thoughtcrime.securesms.util.BackupUtil; import org.thoughtcrime.securesms.util.DateUtils; @@ -648,10 +646,8 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif } private void handleSuccessfulRegistration() { - ApplicationContext.getInstance(RegistrationActivity.this).getJobManager().add(new DirectoryRefreshJob(false)); ApplicationContext.getInstance(RegistrationActivity.this).getJobManager().add(new RotateCertificateJob(RegistrationActivity.this)); - DirectoryRefreshListener.schedule(RegistrationActivity.this); RotateSignedPreKeyListener.schedule(RegistrationActivity.this); Intent nextIntent = getIntent().getParcelableExtra("next_intent"); diff --git a/src/org/thoughtcrime/securesms/contacts/ContactAccessor.java b/src/org/thoughtcrime/securesms/contacts/ContactAccessor.java index 724d9aafa6..5e66a9b12c 100644 --- a/src/org/thoughtcrime/securesms/contacts/ContactAccessor.java +++ b/src/org/thoughtcrime/securesms/contacts/ContactAccessor.java @@ -16,31 +16,19 @@ */ package org.thoughtcrime.securesms.contacts; -import android.content.ContentResolver; import android.content.Context; -import android.database.Cursor; -import android.database.MergeCursor; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; -import android.provider.ContactsContract.CommonDataKinds.Phone; -import android.provider.ContactsContract.Contacts; -import android.provider.ContactsContract.PhoneLookup; -import android.telephony.PhoneNumberUtils; -import android.text.TextUtils; -import network.loki.messenger.R; -import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; import java.util.LinkedList; import java.util.List; -import java.util.Set; + +import network.loki.messenger.R; import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord; @@ -58,91 +46,14 @@ import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord; public class ContactAccessor { - public static final String PUSH_COLUMN = "push"; - private static final ContactAccessor instance = new ContactAccessor(); public static synchronized ContactAccessor getInstance() { return instance; } - public Set
getAllContactsWithNumbers(Context context) { - Set
results = new HashSet<>(); - - try (Cursor cursor = context.getContentResolver().query(Phone.CONTENT_URI, new String[] {Phone.NUMBER}, null ,null, null)) { - while (cursor != null && cursor.moveToNext()) { - if (!TextUtils.isEmpty(cursor.getString(0))) { - results.add(Address.fromExternal(context, cursor.getString(0))); - } - } - } - - return results; - } - - public Cursor getAllSystemContacts(Context context) { - return context.getContentResolver().query(Phone.CONTENT_URI, new String[] {Phone.NUMBER, Phone.DISPLAY_NAME, Phone.LABEL, Phone.PHOTO_URI, Phone._ID, Phone.LOOKUP_KEY}, null, null, null); - } - - public boolean isSystemContact(Context context, String number) { - Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number)); - String[] projection = new String[]{PhoneLookup.DISPLAY_NAME, PhoneLookup.LOOKUP_KEY, - PhoneLookup._ID, PhoneLookup.NUMBER}; - Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null); - - try { - if (cursor != null && cursor.moveToFirst()) { - return true; - } - } finally { - if (cursor != null) cursor.close(); - } - - return false; - } - - public Collection getContactsWithPush(Context context) { - final ContentResolver resolver = context.getContentResolver(); - final String[] inProjection = new String[]{PhoneLookup._ID, PhoneLookup.DISPLAY_NAME}; - - final List
registeredAddresses = DatabaseFactory.getRecipientDatabase(context).getRegistered(); - final Collection lookupData = new ArrayList<>(registeredAddresses.size()); - - for (Address registeredAddress : registeredAddresses) { - Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(registeredAddress.serialize())); - Cursor lookupCursor = resolver.query(uri, inProjection, null, null, null); - - try { - if (lookupCursor != null && lookupCursor.moveToFirst()) { - final ContactData contactData = new ContactData(lookupCursor.getLong(0), lookupCursor.getString(1)); - contactData.numbers.add(new NumberData("TextSecure", registeredAddress.serialize())); - lookupData.add(contactData); - } - } finally { - if (lookupCursor != null) - lookupCursor.close(); - } - } - - return lookupData; - } - public String getNameFromContact(Context context, Uri uri) { - Cursor cursor = null; - - try { - cursor = context.getContentResolver().query(uri, new String[] {Contacts.DISPLAY_NAME}, - null, null, null); - - if (cursor != null && cursor.moveToFirst()) - return cursor.getString(0); - - } finally { - if (cursor != null) - cursor.close(); - } - - return null; + return "Anonymous"; } public ContactData getContactData(Context context, Uri uri) { @@ -150,47 +61,11 @@ public class ContactAccessor { } private ContactData getContactData(Context context, String displayName, long id) { - ContactData contactData = new ContactData(id, displayName); - Cursor numberCursor = null; - - try { - numberCursor = context.getContentResolver().query(Phone.CONTENT_URI, null, - Phone.CONTACT_ID + " = ?", - new String[] {contactData.id + ""}, null); - - while (numberCursor != null && numberCursor.moveToNext()) { - int type = numberCursor.getInt(numberCursor.getColumnIndexOrThrow(Phone.TYPE)); - String label = numberCursor.getString(numberCursor.getColumnIndexOrThrow(Phone.LABEL)); - String number = numberCursor.getString(numberCursor.getColumnIndexOrThrow(Phone.NUMBER)); - String typeLabel = Phone.getTypeLabel(context.getResources(), type, label).toString(); - - contactData.numbers.add(new NumberData(typeLabel, number)); - } - } finally { - if (numberCursor != null) - numberCursor.close(); - } - - return contactData; + return new ContactData(id, displayName); } public List getNumbersForThreadSearchFilter(Context context, String constraint) { LinkedList numberList = new LinkedList<>(); - Cursor cursor = null; - - try { - cursor = context.getContentResolver().query(Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, - Uri.encode(constraint)), - null, null, null, null); - - while (cursor != null && cursor.moveToNext()) { - numberList.add(cursor.getString(cursor.getColumnIndexOrThrow(Phone.NUMBER))); - } - - } finally { - if (cursor != null) - cursor.close(); - } GroupDatabase.Reader reader = null; GroupRecord record; @@ -216,7 +91,7 @@ public class ContactAccessor { } public CharSequence phoneTypeToString(Context mContext, int type, CharSequence label) { - return Phone.getTypeLabel(mContext.getResources(), type, label); + return label; } public static class NumberData implements Parcelable { @@ -294,82 +169,4 @@ public class ContactAccessor { } } - /*** - * If the code below looks shitty to you, that's because it was taken - * directly from the Android source, where shitty code is all you get. - */ - - public Cursor getCursorForRecipientFilter(CharSequence constraint, - ContentResolver mContentResolver) - { - final String SORT_ORDER = Contacts.TIMES_CONTACTED + " DESC," + - Contacts.DISPLAY_NAME + "," + - Contacts.Data.IS_SUPER_PRIMARY + " DESC," + - Phone.TYPE; - - final String[] PROJECTION_PHONE = { - Phone._ID, // 0 - Phone.CONTACT_ID, // 1 - Phone.TYPE, // 2 - Phone.NUMBER, // 3 - Phone.LABEL, // 4 - Phone.DISPLAY_NAME, // 5 - }; - - String phone = ""; - String cons = null; - - if (constraint != null) { - cons = constraint.toString(); - - if (RecipientsAdapter.usefulAsDigits(cons)) { - phone = PhoneNumberUtils.convertKeypadLettersToDigits(cons); - if (phone.equals(cons) && !PhoneNumberUtils.isWellFormedSmsAddress(phone)) { - phone = ""; - } else { - phone = phone.trim(); - } - } - } - Uri uri = Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, Uri.encode(cons)); - String selection = String.format("%s=%s OR %s=%s OR %s=%s", - Phone.TYPE, - Phone.TYPE_MOBILE, - Phone.TYPE, - Phone.TYPE_WORK_MOBILE, - Phone.TYPE, - Phone.TYPE_MMS); - - Cursor phoneCursor = mContentResolver.query(uri, - PROJECTION_PHONE, - null, - null, - SORT_ORDER); - - if (phone.length() > 0) { - ArrayList result = new ArrayList(); - result.add(Integer.valueOf(-1)); // ID - result.add(Long.valueOf(-1)); // CONTACT_ID - result.add(Integer.valueOf(Phone.TYPE_CUSTOM)); // TYPE - result.add(phone); // NUMBER - - /* - * The "\u00A0" keeps Phone.getDisplayLabel() from deciding - * to display the default label ("Home") next to the transformation - * of the letters into numbers. - */ - result.add("\u00A0"); // LABEL - result.add(cons); // NAME - - ArrayList wrap = new ArrayList(); - wrap.add(result); - - ArrayListCursor translated = new ArrayListCursor(PROJECTION_PHONE, wrap); - - return new MergeCursor(new Cursor[] { translated, phoneCursor }); - } else { - return phoneCursor; - } - } - } diff --git a/src/org/thoughtcrime/securesms/contacts/RecipientsAdapter.java b/src/org/thoughtcrime/securesms/contacts/RecipientsAdapter.java index 50f3408b90..430d580cc7 100644 --- a/src/org/thoughtcrime/securesms/contacts/RecipientsAdapter.java +++ b/src/org/thoughtcrime/securesms/contacts/RecipientsAdapter.java @@ -17,9 +17,6 @@ package org.thoughtcrime.securesms.contacts; -import network.loki.messenger.R; -import org.thoughtcrime.securesms.recipients.RecipientsFormatter; - import android.content.ContentResolver; import android.content.Context; import android.database.Cursor; @@ -31,6 +28,10 @@ import android.view.View; import android.widget.ResourceCursorAdapter; import android.widget.TextView; +import org.thoughtcrime.securesms.recipients.RecipientsFormatter; + +import network.loki.messenger.R; + /** * This adapter is used to filter contacts on both name and number. */ @@ -118,7 +119,7 @@ public class RecipientsAdapter extends ResourceCursorAdapter { @Override public Cursor runQueryOnBackgroundThread(CharSequence constraint) { - return mContactAccessor.getCursorForRecipientFilter( constraint, mContentResolver ); + return null; } /** diff --git a/src/org/thoughtcrime/securesms/contactshare/SharedContactDetailsActivity.java b/src/org/thoughtcrime/securesms/contactshare/SharedContactDetailsActivity.java index 942192248d..a41e9d9538 100644 --- a/src/org/thoughtcrime/securesms/contactshare/SharedContactDetailsActivity.java +++ b/src/org/thoughtcrime/securesms/contactshare/SharedContactDetailsActivity.java @@ -20,11 +20,8 @@ import android.widget.TextView; import com.bumptech.glide.load.engine.DiskCacheStrategy; -import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity; -import network.loki.messenger.R; import org.thoughtcrime.securesms.database.RecipientDatabase; -import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob; import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.mms.GlideRequests; import org.thoughtcrime.securesms.recipients.Recipient; @@ -41,7 +38,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import static org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.*; +import network.loki.messenger.R; + +import static org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri; public class SharedContactDetailsActivity extends PassphraseRequiredActionBarActivity implements RecipientModifiedListener { @@ -246,14 +245,4 @@ public class SharedContactDetailsActivity extends PassphraseRequiredActionBarAct engageContainerView.setVisibility(View.GONE); } - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - - if (requestCode == CODE_ADD_EDIT_CONTACT && contact != null) { - ApplicationContext.getInstance(getApplicationContext()) - .getJobManager() - .add(new DirectoryRefreshJob(false)); - } - } } diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java index 8cb1f03570..9e38a84767 100644 --- a/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java +++ b/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java @@ -211,7 +211,6 @@ import org.thoughtcrime.securesms.util.BitmapUtil; import org.thoughtcrime.securesms.util.CommunicationActions; import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.Dialogs; -import org.thoughtcrime.securesms.util.DirectoryHelper; import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme; import org.thoughtcrime.securesms.util.ExpirationUtil; @@ -348,8 +347,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity private int distributionType; private boolean archived; private boolean isSecureText; - private boolean isDefaultSms = true; - private boolean isMmsEnabled = true; + private boolean isDefaultSms = false; + private boolean isMmsEnabled = false; private boolean isSecurityInitialized = false; private int expandedKeyboardHeight = 0; private int collapsedKeyboardHeight = Integer.MAX_VALUE; @@ -1478,41 +1477,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity new AsyncTask() { @Override protected boolean[] doInBackground(Recipient... params) { - Context context = ConversationActivity.this; - Recipient recipient = params[0]; - Log.i(TAG, "Resolving registered state..."); - RegisteredState registeredState; - - if (recipient.isPushGroupRecipient()) { - Log.i(TAG, "Push group recipient..."); - registeredState = RegisteredState.REGISTERED; - } else if (recipient.isResolving()) { - Log.i(TAG, "Talking to DB directly."); - registeredState = DatabaseFactory.getRecipientDatabase(ConversationActivity.this).isRegistered(recipient.getAddress()); - } else { - Log.i(TAG, "Checking through resolved recipient"); - registeredState = recipient.resolve().getRegistered(); - } - - // Loki - Override the flag below - registeredState = RegisteredState.REGISTERED; - - Log.i(TAG, "Resolved registered state: " + registeredState); // Loki - Override the flag below boolean signalEnabled = true; // TextSecurePreferences.isPushRegistered(context); - if (registeredState == RegisteredState.UNKNOWN) { - try { - Log.i(TAG, "Refreshing directory for user: " + recipient.getAddress().serialize()); - registeredState = DirectoryHelper.refreshDirectoryFor(context, recipient); - } catch (IOException e) { - Log.w(TAG, e); - } - } - Log.i(TAG, "Returning registered state..."); - return new boolean[] {registeredState == RegisteredState.REGISTERED && signalEnabled, - Util.isDefaultSmsProvider(context)}; + return new boolean[] { signalEnabled, false}; } @Override diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationFragment.java b/src/org/thoughtcrime/securesms/conversation/ConversationFragment.java index f89f0578de..cb3b53f007 100644 --- a/src/org/thoughtcrime/securesms/conversation/ConversationFragment.java +++ b/src/org/thoughtcrime/securesms/conversation/ConversationFragment.java @@ -77,7 +77,6 @@ import org.thoughtcrime.securesms.database.loaders.ConversationLoader; import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord; import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.database.model.MmsMessageRecord; -import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob; import org.thoughtcrime.securesms.linkpreview.LinkPreview; import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.loki.redesign.views.FriendRequestViewDelegate; @@ -1076,17 +1075,6 @@ public class ConversationFragment extends Fragment } } - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - - if (requestCode == CODE_ADD_EDIT_CONTACT && getContext() != null) { - ApplicationContext.getInstance(getContext().getApplicationContext()) - .getJobManager() - .add(new DirectoryRefreshJob(false)); - } - } - private class ActionModeCallback implements ActionMode.Callback { private int statusBarColor; diff --git a/src/org/thoughtcrime/securesms/jobmanager/migration/WorkManagerFactoryMappings.java b/src/org/thoughtcrime/securesms/jobmanager/migration/WorkManagerFactoryMappings.java index 4957ebd72d..da6e221978 100644 --- a/src/org/thoughtcrime/securesms/jobmanager/migration/WorkManagerFactoryMappings.java +++ b/src/org/thoughtcrime/securesms/jobmanager/migration/WorkManagerFactoryMappings.java @@ -8,7 +8,6 @@ import org.thoughtcrime.securesms.jobs.AttachmentUploadJob; import org.thoughtcrime.securesms.jobs.AvatarDownloadJob; import org.thoughtcrime.securesms.jobs.CleanPreKeysJob; import org.thoughtcrime.securesms.jobs.CreateSignedPreKeyJob; -import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob; import org.thoughtcrime.securesms.jobs.LocalBackupJob; import org.thoughtcrime.securesms.jobs.MmsDownloadJob; import org.thoughtcrime.securesms.jobs.MmsReceiveJob; @@ -57,7 +56,6 @@ public class WorkManagerFactoryMappings { put(AvatarDownloadJob.class.getName(), AvatarDownloadJob.KEY); put(CleanPreKeysJob.class.getName(), CleanPreKeysJob.KEY); put(CreateSignedPreKeyJob.class.getName(), CreateSignedPreKeyJob.KEY); - put(DirectoryRefreshJob.class.getName(), DirectoryRefreshJob.KEY); put(LocalBackupJob.class.getName(), LocalBackupJob.KEY); put(MmsDownloadJob.class.getName(), MmsDownloadJob.KEY); put(MmsReceiveJob.class.getName(), MmsReceiveJob.KEY); diff --git a/src/org/thoughtcrime/securesms/jobs/DirectoryRefreshJob.java b/src/org/thoughtcrime/securesms/jobs/DirectoryRefreshJob.java deleted file mode 100644 index 24d4e7d48b..0000000000 --- a/src/org/thoughtcrime/securesms/jobs/DirectoryRefreshJob.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.thoughtcrime.securesms.jobs; - -import android.app.Application; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import org.thoughtcrime.securesms.database.Address; -import org.thoughtcrime.securesms.jobmanager.Data; -import org.thoughtcrime.securesms.jobmanager.Job; -import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; -import org.thoughtcrime.securesms.logging.Log; -import org.thoughtcrime.securesms.recipients.Recipient; -import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; - -import java.io.IOException; - -public class DirectoryRefreshJob extends BaseJob { - - public static final String KEY = "DirectoryRefreshJob"; - - private static final String TAG = DirectoryRefreshJob.class.getSimpleName(); - - private static final String KEY_ADDRESS = "address"; - private static final String KEY_NOTIFY_OF_NEW_USERS = "notify_of_new_users"; - - @Nullable private Recipient recipient; - private boolean notifyOfNewUsers; - - public DirectoryRefreshJob(boolean notifyOfNewUsers) { - this(null, notifyOfNewUsers); - } - - public DirectoryRefreshJob(@Nullable Recipient recipient, - boolean notifyOfNewUsers) - { - this(new Job.Parameters.Builder() - .setQueue("DirectoryRefreshJob") - .addConstraint(NetworkConstraint.KEY) - .setMaxAttempts(10) - .build(), - recipient, - notifyOfNewUsers); - } - - private DirectoryRefreshJob(@NonNull Job.Parameters parameters, @Nullable Recipient recipient, boolean notifyOfNewUsers) { - super(parameters); - - this.recipient = recipient; - this.notifyOfNewUsers = notifyOfNewUsers; - } - - @Override - public @NonNull Data serialize() { - return new Data.Builder().putString(KEY_ADDRESS, recipient != null ? recipient.getAddress().serialize() : null) - .putBoolean(KEY_NOTIFY_OF_NEW_USERS, notifyOfNewUsers) - .build(); - } - - @Override - public @NonNull String getFactoryKey() { - return KEY; - } - - @Override - public void onRun() throws IOException { - Log.i(TAG, "DirectoryRefreshJob.onRun()"); - -// if (recipient == null) { -// DirectoryHelper.refreshDirectory(context, notifyOfNewUsers); -// } else { -// DirectoryHelper.refreshDirectoryFor(context, recipient); -// } - } - - @Override - public boolean onShouldRetry(@NonNull Exception exception) { - if (exception instanceof PushNetworkException) return true; - return false; - } - - @Override - public void onCanceled() {} - - public static final class Factory implements Job.Factory { - - private final Application application; - - public Factory(@NonNull Application application) { - this.application = application; - } - - @Override - public @NonNull DirectoryRefreshJob create(@NonNull Parameters parameters, @NonNull Data data) { - String serializedAddress = data.getString(KEY_ADDRESS); - Address address = serializedAddress != null ? Address.fromSerialized(serializedAddress) : null; - Recipient recipient = address != null ? Recipient.from(application, address, true) : null; - boolean notifyOfNewUsers = data.getBoolean(KEY_NOTIFY_OF_NEW_USERS); - - return new DirectoryRefreshJob(parameters, recipient, notifyOfNewUsers); - } - } -} diff --git a/src/org/thoughtcrime/securesms/jobs/JobManagerFactories.java b/src/org/thoughtcrime/securesms/jobs/JobManagerFactories.java index 3a375a6169..5300f461fd 100644 --- a/src/org/thoughtcrime/securesms/jobs/JobManagerFactories.java +++ b/src/org/thoughtcrime/securesms/jobs/JobManagerFactories.java @@ -31,7 +31,6 @@ public final class JobManagerFactories { put(AvatarDownloadJob.KEY, new AvatarDownloadJob.Factory()); put(CleanPreKeysJob.KEY, new CleanPreKeysJob.Factory()); put(CreateSignedPreKeyJob.KEY, new CreateSignedPreKeyJob.Factory()); - put(DirectoryRefreshJob.KEY, new DirectoryRefreshJob.Factory(application)); put(LocalBackupJob.KEY, new LocalBackupJob.Factory()); put(MmsDownloadJob.KEY, new MmsDownloadJob.Factory()); put(MmsReceiveJob.KEY, new MmsReceiveJob.Factory()); diff --git a/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java index 088a426e96..1447b5bafd 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java @@ -224,7 +224,6 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType { if (messageId >= 0) { database.markAsPendingInsecureSmsFallback(messageId); notifyMediaMessageDeliveryFailed(context, messageId); - ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(false)); } } catch (UntrustedIdentityException uie) { warn(TAG, "Failure", uie); diff --git a/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java b/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java index f9dbfeea25..053ab5d79e 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java @@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.jobs; import android.annotation.SuppressLint; import android.support.annotation.NonNull; -import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId; @@ -32,7 +31,6 @@ public abstract class PushReceivedJob extends BaseJob { if (!isActiveNumber(recipient)) { DatabaseFactory.getRecipientDatabase(context).setRegistered(recipient, RecipientDatabase.RegisteredState.REGISTERED); - ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(recipient, false)); } } diff --git a/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java index 6d44fc9b5c..5ce7dd3442 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java @@ -165,7 +165,6 @@ public class PushTextSendJob extends PushSendJob implements InjectableType { if (messageId >= 0) { database.markAsPendingInsecureSmsFallback(record.getId()); MessageNotifier.notifyMessageDeliveryFailed(context, record.getRecipient(), record.getThreadId()); - ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(false)); } } catch (UntrustedIdentityException e) { warn(TAG, "Failure", e); diff --git a/src/org/thoughtcrime/securesms/loki/redesign/activities/LinkedDevicesActivity.kt b/src/org/thoughtcrime/securesms/loki/redesign/activities/LinkedDevicesActivity.kt index d9147fbfdd..0c3e290556 100644 --- a/src/org/thoughtcrime/securesms/loki/redesign/activities/LinkedDevicesActivity.kt +++ b/src/org/thoughtcrime/securesms/loki/redesign/activities/LinkedDevicesActivity.kt @@ -12,7 +12,9 @@ import android.view.View import android.widget.Toast import kotlinx.android.synthetic.main.activity_linked_devices.* import network.loki.messenger.R +import nl.komponents.kovenant.Kovenant import nl.komponents.kovenant.functional.bind +import nl.komponents.kovenant.task import nl.komponents.kovenant.ui.failUi import nl.komponents.kovenant.ui.successUi import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity @@ -24,8 +26,8 @@ import org.thoughtcrime.securesms.loki.signAndSendDeviceLinkMessage import org.thoughtcrime.securesms.sms.MessageSender import org.thoughtcrime.securesms.util.TextSecurePreferences import org.whispersystems.signalservice.loki.api.DeviceLink -import org.whispersystems.signalservice.loki.api.LokiAPI import org.whispersystems.signalservice.loki.api.LokiFileServerAPI +import org.whispersystems.signalservice.loki.utilities.createContext import java.util.* import kotlin.concurrent.schedule @@ -145,7 +147,11 @@ class LinkedDevicesActivity : PassphraseRequiredActionBarActivity, LoaderManager } override fun onDeviceLinkRequestAuthorized(deviceLink: DeviceLink) { - LokiFileServerAPI.shared.addDeviceLink(deviceLink).bind(LokiAPI.sharedWorkContext) { + val context = Kovenant.createContext("Multi-device") + LokiFileServerAPI.shared.addDeviceLink(deviceLink) + task(context) { + 1 + }.bind { signAndSendDeviceLinkMessage(this, deviceLink) }.successUi { LoaderManager.getInstance(this).restartLoader(0, null, this) diff --git a/src/org/thoughtcrime/securesms/service/DirectoryRefreshListener.java b/src/org/thoughtcrime/securesms/service/DirectoryRefreshListener.java deleted file mode 100644 index 8abacdca4d..0000000000 --- a/src/org/thoughtcrime/securesms/service/DirectoryRefreshListener.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.thoughtcrime.securesms.service; - - -import android.content.Context; -import android.content.Intent; - -import org.thoughtcrime.securesms.ApplicationContext; -import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob; -import org.thoughtcrime.securesms.util.TextSecurePreferences; - -import java.util.concurrent.TimeUnit; - -public class DirectoryRefreshListener extends PersistentAlarmManagerListener { - - private static final long INTERVAL = TimeUnit.HOURS.toMillis(12); - - @Override - protected long getNextScheduledExecutionTime(Context context) { - return TextSecurePreferences.getDirectoryRefreshTime(context); - } - - @Override - protected long onAlarm(Context context, long scheduledTime) { - if (scheduledTime != 0 && TextSecurePreferences.isPushRegistered(context)) { - ApplicationContext.getInstance(context) - .getJobManager() - .add(new DirectoryRefreshJob(true)); - } - - long newTime = System.currentTimeMillis() + INTERVAL; - TextSecurePreferences.setDirectoryRefreshTime(context, newTime); - - return newTime; - } - - public static void schedule(Context context) { - new DirectoryRefreshListener().onReceive(context, new Intent()); - } -} diff --git a/src/org/thoughtcrime/securesms/util/DirectoryHelper.java b/src/org/thoughtcrime/securesms/util/DirectoryHelper.java deleted file mode 100644 index 7b0fa1c712..0000000000 --- a/src/org/thoughtcrime/securesms/util/DirectoryHelper.java +++ /dev/null @@ -1,520 +0,0 @@ -package org.thoughtcrime.securesms.util; - -import android.Manifest; -import android.accounts.Account; -import android.accounts.AccountManager; -import android.annotation.SuppressLint; -import android.content.ContentResolver; -import android.content.Context; -import android.content.OperationApplicationException; -import android.database.Cursor; -import android.net.Uri; -import android.os.RemoteException; -import android.provider.ContactsContract; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.text.TextUtils; -import org.thoughtcrime.securesms.logging.Log; - -import com.annimon.stream.Collectors; -import com.annimon.stream.Stream; - -import org.thoughtcrime.securesms.ApplicationContext; -import network.loki.messenger.BuildConfig; -import network.loki.messenger.R; -import org.thoughtcrime.securesms.contacts.ContactAccessor; -import org.thoughtcrime.securesms.crypto.SessionUtil; -import org.thoughtcrime.securesms.database.Address; -import org.thoughtcrime.securesms.database.DatabaseFactory; -import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult; -import org.thoughtcrime.securesms.database.RecipientDatabase; -import org.thoughtcrime.securesms.database.RecipientDatabase.RegisteredState; -import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob; -import org.thoughtcrime.securesms.notifications.MessageNotifier; -import org.thoughtcrime.securesms.notifications.NotificationChannels; -import org.thoughtcrime.securesms.permissions.Permissions; -import org.thoughtcrime.securesms.push.AccountManagerFactory; -import org.thoughtcrime.securesms.push.IasTrustStore; -import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.sms.IncomingJoinedMessage; -import org.thoughtcrime.securesms.util.concurrent.SignalExecutors; -import org.whispersystems.libsignal.util.guava.Optional; -import org.whispersystems.signalservice.api.SignalServiceAccountManager; -import org.whispersystems.signalservice.api.push.ContactTokenDetails; -import org.whispersystems.signalservice.api.push.TrustStore; -import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; -import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; -import org.whispersystems.signalservice.internal.contacts.crypto.Quote; -import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedQuoteException; -import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedResponseException; - -import java.io.IOException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.SignatureException; -import java.security.cert.CertificateException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; - -public class DirectoryHelper { - - private static final String TAG = DirectoryHelper.class.getSimpleName(); - - private static final int CONTACT_DISCOVERY_BATCH_SIZE = 2048; - - public static void refreshDirectory(@NonNull Context context, boolean notifyOfNewUsers) - throws IOException - { - if (TextUtils.isEmpty(TextSecurePreferences.getLocalNumber(context))) return; - if (!Permissions.hasAll(context, Manifest.permission.WRITE_CONTACTS)) return; - - List
newlyActiveUsers = refreshDirectory(context, AccountManagerFactory.createManager(context)); - - if (TextSecurePreferences.isMultiDevice(context)) { - ApplicationContext.getInstance(context) - .getJobManager() - .add(new MultiDeviceContactUpdateJob(context)); - } - - if (notifyOfNewUsers) notifyNewUsers(context, newlyActiveUsers); - } - - @SuppressLint("CheckResult") - private static @NonNull List
refreshDirectory(@NonNull Context context, @NonNull SignalServiceAccountManager accountManager) - throws IOException - { - if (TextUtils.isEmpty(TextSecurePreferences.getLocalNumber(context))) { - return Collections.emptyList(); - } - - if (!Permissions.hasAll(context, Manifest.permission.WRITE_CONTACTS)) { - return Collections.emptyList(); - } - - RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context); - Stream eligibleRecipientDatabaseContactNumbers = Stream.of(recipientDatabase.getAllAddresses()).filter(Address::isPhone).map(Address::toPhoneString); - Stream eligibleSystemDatabaseContactNumbers = Stream.of(ContactAccessor.getInstance().getAllContactsWithNumbers(context)).map(Address::serialize); - Set eligibleContactNumbers = Stream.concat(eligibleRecipientDatabaseContactNumbers, eligibleSystemDatabaseContactNumbers).collect(Collectors.toSet()); - - Future legacyRequest = getLegacyDirectoryResult(context, accountManager, recipientDatabase, eligibleContactNumbers); - List>> contactServiceRequest = getContactServiceDirectoryResult(context, accountManager, eligibleContactNumbers); - - try { - DirectoryResult legacyResult = legacyRequest.get(); - Optional> contactServiceResult = executeAndMergeContactDiscoveryRequests(accountManager, contactServiceRequest); - - if (!contactServiceResult.isPresent()) { - Log.i(TAG, "[Batch] New contact discovery service failed, so we're skipping the comparison."); - return legacyResult.getNewlyActiveAddresses(); - } - - if (legacyResult.getNumbers().size() == contactServiceResult.get().size() && legacyResult.getNumbers().containsAll(contactServiceResult.get())) { - Log.i(TAG, "[Batch] New contact discovery service request matched existing results."); - accountManager.reportContactDiscoveryServiceMatch(); - } else { - Log.w(TAG, "[Batch] New contact discovery service request did NOT match existing results."); - accountManager.reportContactDiscoveryServiceMismatch(); - } - - return legacyResult.getNewlyActiveAddresses(); - - } catch (InterruptedException e) { - throw new IOException("[Batch] Operation was interrupted.", e); - } catch (ExecutionException e) { - if (e.getCause() instanceof IOException) { - throw (IOException) e.getCause(); - } else { - Log.e(TAG, "[Batch] Experienced an unexpected exception.", e); - throw new AssertionError(e); - } - } - } - - public static RegisteredState refreshDirectoryFor(@NonNull Context context, - @NonNull Recipient recipient) - throws IOException - { - RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context); - SignalServiceAccountManager accountManager = AccountManagerFactory.createManager(context); - - Future legacyRequest = getLegacyRegisteredState(context, accountManager, recipientDatabase, recipient); - List>> contactServiceRequest = getContactServiceDirectoryResult(context, accountManager, Collections.singleton(recipient.getAddress().serialize())); - - try { - RegisteredState legacyState = legacyRequest.get(); - Optional> contactServiceResult = executeAndMergeContactDiscoveryRequests(accountManager, contactServiceRequest); - - if (!contactServiceResult.isPresent()) { - Log.i(TAG, "[Singular] New contact discovery service failed, so we're skipping the comparison."); - return legacyState; - } - - RegisteredState contactServiceState = contactServiceResult.get().size() == 1 ? RegisteredState.REGISTERED : RegisteredState.NOT_REGISTERED; - - if (legacyState == contactServiceState) { - Log.i(TAG, "[Singular] New contact discovery service request matched existing results."); - accountManager.reportContactDiscoveryServiceMatch(); - } else { - Log.w(TAG, "[Singular] New contact discovery service request did NOT match existing results."); - accountManager.reportContactDiscoveryServiceMismatch(); - } - - return legacyState; - - } catch (InterruptedException e) { - throw new IOException("[Singular] Operation was interrupted.", e); - } catch (ExecutionException e) { - if (e.getCause() instanceof IOException) { - throw (IOException) e.getCause(); - } else { - Log.e(TAG, "[Singular] Experienced an unexpected exception.", e); - throw new AssertionError(e); - } - } - } - - private static void updateContactsDatabase(@NonNull Context context, @NonNull List
activeAddresses, boolean removeMissing) { - Optional account = getOrCreateAccount(context); - - if (account.isPresent()) { - try { - DatabaseFactory.getContactsDatabase(context).removeDeletedRawContacts(account.get().getAccount()); - DatabaseFactory.getContactsDatabase(context).setRegisteredUsers(account.get().getAccount(), activeAddresses, removeMissing); - - Cursor cursor = ContactAccessor.getInstance().getAllSystemContacts(context); - RecipientDatabase.BulkOperationsHandle handle = DatabaseFactory.getRecipientDatabase(context).resetAllSystemContactInfo(); - - try { - while (cursor != null && cursor.moveToNext()) { - String number = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER)); - - if (!TextUtils.isEmpty(number)) { - Address address = Address.fromExternal(context, number); - String displayName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); - String contactPhotoUri = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.PHOTO_URI)); - String contactLabel = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.LABEL)); - Uri contactUri = ContactsContract.Contacts.getLookupUri(cursor.getLong(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone._ID)), - cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.LOOKUP_KEY))); - - handle.setSystemContactInfo(address, displayName, contactPhotoUri, contactLabel, contactUri.toString()); - } - } - } finally { - handle.finish(); - } - - if (NotificationChannels.supported()) { - try (RecipientDatabase.RecipientReader recipients = DatabaseFactory.getRecipientDatabase(context).getRecipientsWithNotificationChannels()) { - Recipient recipient; - while ((recipient = recipients.getNext()) != null) { - NotificationChannels.updateContactChannelName(context, recipient); - } - } - } - } catch (RemoteException | OperationApplicationException e) { - Log.w(TAG, "Failed to update contacts.", e); - } - } - } - - private static void notifyNewUsers(@NonNull Context context, - @NonNull List
newUsers) - { - if (!TextSecurePreferences.isNewContactsNotificationEnabled(context)) return; - - for (Address newUser: newUsers) { - if (!SessionUtil.hasSession(context, newUser) && !Util.isOwnNumber(context, newUser)) { - IncomingJoinedMessage message = new IncomingJoinedMessage(newUser); - Optional insertResult = DatabaseFactory.getSmsDatabase(context).insertMessageInbox(message); - - if (insertResult.isPresent()) { - int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY); - if (hour >= 9 && hour < 23) { - MessageNotifier.updateNotification(context, insertResult.get().getThreadId(), true); - } else { - MessageNotifier.updateNotification(context, insertResult.get().getThreadId(), false); - } - } - } - } - } - - private static Optional getOrCreateAccount(Context context) { - AccountManager accountManager = AccountManager.get(context); - Account[] accounts = accountManager.getAccountsByType("org.thoughtcrime.securesms"); - - Optional account; - - if (accounts.length == 0) account = createAccount(context); - else account = Optional.of(new AccountHolder(accounts[0], false)); - - if (account.isPresent() && !ContentResolver.getSyncAutomatically(account.get().getAccount(), ContactsContract.AUTHORITY)) { - ContentResolver.setSyncAutomatically(account.get().getAccount(), ContactsContract.AUTHORITY, true); - } - - return account; - } - - private static Optional createAccount(Context context) { - AccountManager accountManager = AccountManager.get(context); - Account account = new Account(context.getString(R.string.app_name), "org.thoughtcrime.securesms"); - - if (accountManager.addAccountExplicitly(account, null, null)) { - Log.i(TAG, "Created new account..."); - ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1); - return Optional.of(new AccountHolder(account, true)); - } else { - Log.w(TAG, "Failed to create account!"); - return Optional.absent(); - } - } - - private static Future getLegacyDirectoryResult(@NonNull Context context, - @NonNull SignalServiceAccountManager accountManager, - @NonNull RecipientDatabase recipientDatabase, - @NonNull Set eligibleContactNumbers) - { - return SignalExecutors.UNBOUNDED.submit(() -> { - List activeTokens = accountManager.getContacts(eligibleContactNumbers); - - if (activeTokens != null) { - List
activeAddresses = new LinkedList<>(); - List
inactiveAddresses = new LinkedList<>(); - - Set inactiveContactNumbers = new HashSet<>(eligibleContactNumbers); - - for (ContactTokenDetails activeToken : activeTokens) { - activeAddresses.add(Address.fromSerialized(activeToken.getNumber())); - inactiveContactNumbers.remove(activeToken.getNumber()); - } - - for (String inactiveContactNumber : inactiveContactNumbers) { - inactiveAddresses.add(Address.fromSerialized(inactiveContactNumber)); - } - - Set
currentActiveAddresses = new HashSet<>(recipientDatabase.getRegistered()); - Set
contactAddresses = new HashSet<>(recipientDatabase.getSystemContacts()); - List
newlyActiveAddresses = Stream.of(activeAddresses) - .filter(address -> !currentActiveAddresses.contains(address)) - .filter(contactAddresses::contains) - .toList(); - - recipientDatabase.setRegistered(activeAddresses, inactiveAddresses); - updateContactsDatabase(context, activeAddresses, true); - - Set activeContactNumbers = Stream.of(activeAddresses).map(Address::serialize).collect(Collectors.toSet()); - - if (TextSecurePreferences.hasSuccessfullyRetrievedDirectory(context)) { - return new DirectoryResult(activeContactNumbers, newlyActiveAddresses); - } else { - TextSecurePreferences.setHasSuccessfullyRetrievedDirectory(context, true); - return new DirectoryResult(activeContactNumbers); - } - } - return new DirectoryResult(Collections.emptySet(), Collections.emptyList()); - }); - } - - private static Future getLegacyRegisteredState(@NonNull Context context, - @NonNull SignalServiceAccountManager accountManager, - @NonNull RecipientDatabase recipientDatabase, - @NonNull Recipient recipient) - { - return SignalExecutors.UNBOUNDED.submit(() -> { - boolean activeUser = recipient.resolve().getRegistered() == RegisteredState.REGISTERED; - boolean systemContact = recipient.isSystemContact(); - String number = recipient.getAddress().serialize(); - Optional details = accountManager.getContact(number); - - if (details.isPresent()) { - recipientDatabase.setRegistered(recipient, RegisteredState.REGISTERED); - - if (Permissions.hasAll(context, Manifest.permission.WRITE_CONTACTS)) { - updateContactsDatabase(context, Util.asList(recipient.getAddress()), false); - } - - if (!activeUser && TextSecurePreferences.isMultiDevice(context)) { - ApplicationContext.getInstance(context).getJobManager().add(new MultiDeviceContactUpdateJob(context)); - } - - if (!activeUser && systemContact && !TextSecurePreferences.getNeedsSqlCipherMigration(context)) { - notifyNewUsers(context, Collections.singletonList(recipient.getAddress())); - } - - return RegisteredState.REGISTERED; - } else { - recipientDatabase.setRegistered(recipient, RegisteredState.NOT_REGISTERED); - return RegisteredState.NOT_REGISTERED; - } - }); - } - - private static List>> getContactServiceDirectoryResult(@NonNull Context context, - @NonNull SignalServiceAccountManager accountManager, - @NonNull Set eligibleContactNumbers) - { - Set sanitizedNumbers = sanitizeNumbers(eligibleContactNumbers); - List> batches = splitIntoBatches(sanitizedNumbers, CONTACT_DISCOVERY_BATCH_SIZE); - List>> futures = new ArrayList<>(batches.size()); - KeyStore iasKeyStore = getIasKeyStore(context); - - for (Set batch : batches) { - Future> future = SignalExecutors.UNBOUNDED.submit(() -> { - return new HashSet<>(accountManager.getRegisteredUsers(iasKeyStore, batch, BuildConfig.MRENCLAVE)); - }); - futures.add(future); - } - return futures; - } - - private static Set sanitizeNumbers(@NonNull Set numbers) { - return Stream.of(numbers).filter(number -> { - try { - return number.startsWith("+") && number.length() > 1 && Long.parseLong(number.substring(1)) > 0; - } catch (NumberFormatException e) { - return false; - } - }).collect(Collectors.toSet()); - } - - private static List> splitIntoBatches(@NonNull Set numbers, int batchSize) { - List numberList = new ArrayList<>(numbers); - List> batches = new LinkedList<>(); - - for (int i = 0; i < numberList.size(); i += batchSize) { - List batch = numberList.subList(i, Math.min(numberList.size(), i + batchSize)); - batches.add(new HashSet<>(batch)); - } - - return batches; - } - - private static Optional> executeAndMergeContactDiscoveryRequests(@NonNull SignalServiceAccountManager accountManager, @NonNull List>> futures) { - Set results = new HashSet<>(); - try { - for (Future> future : futures) { - results.addAll(future.get()); - } - } catch (InterruptedException e) { - Log.w(TAG, "Contact discovery batch was interrupted.", e); - accountManager.reportContactDiscoveryServiceUnexpectedError(buildErrorReason(e)); - return Optional.absent(); - } catch (ExecutionException e) { - if (isAttestationError(e.getCause())) { - Log.w(TAG, "Failed during attestation.", e); - accountManager.reportContactDiscoveryServiceAttestationError(buildErrorReason(e.getCause())); - return Optional.absent(); - } else if (e.getCause() instanceof PushNetworkException) { - Log.w(TAG, "Failed due to poor network.", e); - return Optional.absent(); - } else if (e.getCause() instanceof NonSuccessfulResponseCodeException) { - Log.w(TAG, "Failed due to non successful response code.", e); - return Optional.absent(); - } else { - Log.w(TAG, "Failed for an unknown reason.", e); - accountManager.reportContactDiscoveryServiceUnexpectedError(buildErrorReason(e.getCause())); - return Optional.absent(); - } - } - - return Optional.of(results); - } - - private static boolean isAttestationError(Throwable e) { - return e instanceof CertificateException || - e instanceof SignatureException || - e instanceof UnauthenticatedQuoteException || - e instanceof UnauthenticatedResponseException || - e instanceof Quote.InvalidQuoteFormatException; - } - - private static KeyStore getIasKeyStore(@NonNull Context context) { - try { - TrustStore contactTrustStore = new IasTrustStore(context); - - KeyStore keyStore = KeyStore.getInstance("BKS"); - keyStore.load(contactTrustStore.getKeyStoreInputStream(), contactTrustStore.getKeyStorePassword().toCharArray()); - - return keyStore; - } catch (KeyStoreException | CertificateException | IOException | NoSuchAlgorithmException e) { - throw new AssertionError(e); - } - } - - private static String buildErrorReason(@Nullable Throwable t) { - if (t == null) { - return "null"; - } - - String rawString = android.util.Log.getStackTraceString(t); - List lines = Arrays.asList(rawString.split("\\n")); - - String errorString; - - if (lines.size() > 1) { - errorString = t.getClass().getName() + "\n" + Util.join(lines.subList(1, lines.size()), "\n"); - } else { - errorString = t.getClass().getName(); - } - - if (errorString.length() > 1000) { - return errorString.substring(0, 1000); - } else { - return errorString; - } - } - - private static class DirectoryResult { - - private final Set numbers; - private final List
newlyActiveAddresses; - - DirectoryResult(@NonNull Set numbers) { - this(numbers, Collections.emptyList()); - } - - DirectoryResult(@NonNull Set numbers, @NonNull List
newlyActiveAddresses) { - this.numbers = numbers; - this.newlyActiveAddresses = newlyActiveAddresses; - } - - Set getNumbers() { - return numbers; - } - - List
getNewlyActiveAddresses() { - return newlyActiveAddresses; - } - } - - private static class AccountHolder { - - private final boolean fresh; - private final Account account; - - private AccountHolder(Account account, boolean fresh) { - this.fresh = fresh; - this.account = account; - } - - @SuppressWarnings("unused") - public boolean isFresh() { - return fresh; - } - - public Account getAccount() { - return account; - } - - } - -}