mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-27 12:05:22 +00:00
Use SIM country code when registered number is unavailable
Convert directory operations to Addresses Fixes #6845 // FREEBIE
This commit is contained in:
parent
4838fade6c
commit
7f46e99f9c
@ -1023,8 +1023,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
capabilities.getVideoCapability() == Capability.UNKNOWN)
|
||||
{
|
||||
try {
|
||||
capabilities = DirectoryHelper.refreshDirectoryFor(context, masterSecret, recipients,
|
||||
TextSecurePreferences.getLocalNumber(context));
|
||||
capabilities = DirectoryHelper.refreshDirectoryFor(context, masterSecret, recipients);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ import android.widget.Toast;
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.GoogleApiAvailability;
|
||||
import com.google.i18n.phonenumbers.AsYouTypeFormatter;
|
||||
import com.google.i18n.phonenumbers.NumberParseException;
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
||||
import com.google.i18n.phonenumbers.Phonenumber;
|
||||
|
||||
@ -32,6 +31,7 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.util.Dialogs;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
|
||||
|
||||
/**
|
||||
@ -147,26 +147,17 @@ public class RegistrationActivity extends BaseActionBarActivity {
|
||||
}
|
||||
|
||||
private void initializeNumber() {
|
||||
PhoneNumberUtil numberUtil = PhoneNumberUtil.getInstance();
|
||||
String localNumber = Util.getDeviceE164Number(this);
|
||||
Optional<Phonenumber.PhoneNumber> localNumber = Util.getDeviceNumber(this);
|
||||
|
||||
try {
|
||||
if (!TextUtils.isEmpty(localNumber)) {
|
||||
Phonenumber.PhoneNumber localNumberObject = numberUtil.parse(localNumber, null);
|
||||
if (localNumber.isPresent()) {
|
||||
this.countryCode.setText(String.valueOf(localNumber.get().getCountryCode()));
|
||||
this.number.setText(String.valueOf(localNumber.get().getNationalNumber()));
|
||||
} else {
|
||||
Optional<String> simCountryIso = Util.getSimCountryIso(this);
|
||||
|
||||
if (localNumberObject != null) {
|
||||
this.countryCode.setText(String.valueOf(localNumberObject.getCountryCode()));
|
||||
this.number.setText(String.valueOf(localNumberObject.getNationalNumber()));
|
||||
}
|
||||
} else {
|
||||
String simCountryIso = Util.getSimCountryIso(this);
|
||||
|
||||
if (!TextUtils.isEmpty(simCountryIso)) {
|
||||
this.countryCode.setText(numberUtil.getCountryCodeForRegion(simCountryIso)+"");
|
||||
}
|
||||
if (simCountryIso.isPresent() && !TextUtils.isEmpty(simCountryIso.get())) {
|
||||
this.countryCode.setText(PhoneNumberUtil.getInstance().getCountryCodeForRegion(simCountryIso.get())+"");
|
||||
}
|
||||
} catch (NumberParseException npe) {
|
||||
Log.w(TAG, npe);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.push.ContactTokenDetails;
|
||||
@ -76,29 +77,28 @@ public class ContactsDatabase {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public synchronized @NonNull List<String> setRegisteredUsers(@NonNull Account account,
|
||||
@NonNull String localNumber,
|
||||
@NonNull List<ContactTokenDetails> registeredContacts,
|
||||
boolean remove)
|
||||
public synchronized @NonNull List<Address> setRegisteredUsers(@NonNull Account account,
|
||||
@NonNull List<ContactTokenDetails> registeredContacts,
|
||||
boolean remove)
|
||||
throws RemoteException, OperationApplicationException
|
||||
{
|
||||
|
||||
Map<String, ContactTokenDetails> registeredNumbers = new HashMap<>();
|
||||
List<String> addedNumbers = new LinkedList<>();
|
||||
ArrayList<ContentProviderOperation> operations = new ArrayList<>();
|
||||
Map<String, SignalContact> currentContacts = getSignalRawContacts(account, localNumber);
|
||||
Map<Address, ContactTokenDetails> registeredAddresses = new HashMap<>();
|
||||
List<Address> addedAddresses = new LinkedList<>();
|
||||
ArrayList<ContentProviderOperation> operations = new ArrayList<>();
|
||||
Map<Address, SignalContact> currentContacts = getSignalRawContacts(account);
|
||||
|
||||
for (ContactTokenDetails registeredContact : registeredContacts) {
|
||||
String registeredNumber = registeredContact.getNumber();
|
||||
Address registeredAddress = Address.fromSerialized(registeredContact.getNumber());
|
||||
|
||||
registeredNumbers.put(registeredNumber, registeredContact);
|
||||
registeredAddresses.put(registeredAddress, registeredContact);
|
||||
|
||||
if (!currentContacts.containsKey(registeredNumber)) {
|
||||
Optional<SystemContactInfo> systemContactInfo = getSystemContactInfo(registeredNumber, localNumber);
|
||||
if (!currentContacts.containsKey(registeredAddress)) {
|
||||
Optional<SystemContactInfo> systemContactInfo = getSystemContactInfo(registeredAddress);
|
||||
|
||||
if (systemContactInfo.isPresent()) {
|
||||
Log.w(TAG, "Adding number: " + registeredNumber);
|
||||
addedNumbers.add(registeredNumber);
|
||||
Log.w(TAG, "Adding number: " + registeredAddress);
|
||||
addedAddresses.add(registeredAddress);
|
||||
addTextSecureRawContact(operations, account, systemContactInfo.get().number,
|
||||
systemContactInfo.get().name, systemContactInfo.get().id,
|
||||
true);
|
||||
@ -106,8 +106,8 @@ public class ContactsDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<String, SignalContact> currentContactEntry : currentContacts.entrySet()) {
|
||||
ContactTokenDetails tokenDetails = registeredNumbers.get(currentContactEntry.getKey());
|
||||
for (Map.Entry<Address, SignalContact> currentContactEntry : currentContacts.entrySet()) {
|
||||
ContactTokenDetails tokenDetails = registeredAddresses.get(currentContactEntry.getKey());
|
||||
|
||||
if (tokenDetails == null) {
|
||||
if (remove) {
|
||||
@ -129,7 +129,7 @@ public class ContactsDatabase {
|
||||
context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operations);
|
||||
}
|
||||
|
||||
return addedNumbers;
|
||||
return addedAddresses;
|
||||
}
|
||||
|
||||
@NonNull Cursor querySystemContacts(String filter) {
|
||||
@ -220,7 +220,7 @@ public class ContactsDatabase {
|
||||
}
|
||||
|
||||
private void addContactVoiceSupport(List<ContentProviderOperation> operations,
|
||||
@NonNull String e164number, long rawContactId)
|
||||
@NonNull Address address, long rawContactId)
|
||||
{
|
||||
operations.add(ContentProviderOperation.newUpdate(RawContacts.CONTENT_URI)
|
||||
.withSelection(RawContacts._ID + " = ?", new String[] {String.valueOf(rawContactId)})
|
||||
@ -230,9 +230,9 @@ public class ContactsDatabase {
|
||||
operations.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI.buildUpon().appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build())
|
||||
.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactId)
|
||||
.withValue(ContactsContract.Data.MIMETYPE, CALL_MIMETYPE)
|
||||
.withValue(ContactsContract.Data.DATA1, e164number)
|
||||
.withValue(ContactsContract.Data.DATA1, address.toPhoneString())
|
||||
.withValue(ContactsContract.Data.DATA2, context.getString(R.string.app_name))
|
||||
.withValue(ContactsContract.Data.DATA3, context.getString(R.string.ContactsDatabase_signal_call_s, e164number))
|
||||
.withValue(ContactsContract.Data.DATA3, context.getString(R.string.ContactsDatabase_signal_call_s, address.toPhoneString()))
|
||||
.withYieldAllowed(true)
|
||||
.build());
|
||||
}
|
||||
@ -346,15 +346,13 @@ public class ContactsDatabase {
|
||||
.build());
|
||||
}
|
||||
|
||||
private @NonNull Map<String, SignalContact> getSignalRawContacts(@NonNull Account account,
|
||||
@NonNull String localNumber)
|
||||
{
|
||||
private @NonNull Map<Address, SignalContact> getSignalRawContacts(@NonNull Account account) {
|
||||
Uri currentContactsUri = RawContacts.CONTENT_URI.buildUpon()
|
||||
.appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name)
|
||||
.appendQueryParameter(RawContacts.ACCOUNT_TYPE, account.type).build();
|
||||
|
||||
Map<String, SignalContact> signalContacts = new HashMap<>();
|
||||
Cursor cursor = null;
|
||||
Map<Address, SignalContact> signalContacts = new HashMap<>();
|
||||
Cursor cursor = null;
|
||||
|
||||
try {
|
||||
String[] projection;
|
||||
@ -368,21 +366,13 @@ public class ContactsDatabase {
|
||||
cursor = context.getContentResolver().query(currentContactsUri, projection, null, null, null);
|
||||
|
||||
while (cursor != null && cursor.moveToNext()) {
|
||||
String currentNumber;
|
||||
|
||||
try {
|
||||
currentNumber = PhoneNumberFormatter.formatNumber(cursor.getString(1), localNumber);
|
||||
} catch (InvalidNumberException e) {
|
||||
Log.w(TAG, e);
|
||||
currentNumber = cursor.getString(1);
|
||||
}
|
||||
|
||||
long rawContactId = cursor.getLong(0);
|
||||
long contactId = cursor.getLong(3);
|
||||
String supportsVoice = cursor.getString(2);
|
||||
String rawContactDisplayName = null;
|
||||
String aggregateDisplayName = null;
|
||||
int rawContactDisplayNameSource = 0;
|
||||
Address currentAddress = Address.fromExternal(context, cursor.getString(1));
|
||||
long rawContactId = cursor.getLong(0);
|
||||
long contactId = cursor.getLong(3);
|
||||
String supportsVoice = cursor.getString(2);
|
||||
String rawContactDisplayName = null;
|
||||
String aggregateDisplayName = null;
|
||||
int rawContactDisplayNameSource = 0;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
rawContactDisplayName = cursor.getString(4);
|
||||
@ -390,7 +380,7 @@ public class ContactsDatabase {
|
||||
aggregateDisplayName = getDisplayName(contactId);
|
||||
}
|
||||
|
||||
signalContacts.put(currentNumber, new SignalContact(rawContactId, supportsVoice, rawContactDisplayName, aggregateDisplayName, rawContactDisplayNameSource));
|
||||
signalContacts.put(currentAddress, new SignalContact(rawContactId, supportsVoice, rawContactDisplayName, aggregateDisplayName, rawContactDisplayNameSource));
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null)
|
||||
@ -400,10 +390,11 @@ public class ContactsDatabase {
|
||||
return signalContacts;
|
||||
}
|
||||
|
||||
private Optional<SystemContactInfo> getSystemContactInfo(@NonNull String e164number,
|
||||
@NonNull String localNumber)
|
||||
private Optional<SystemContactInfo> getSystemContactInfo(@NonNull Address address)
|
||||
{
|
||||
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(e164number));
|
||||
if (!address.isPhone()) return Optional.absent();
|
||||
|
||||
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(address.toPhoneString()));
|
||||
String[] projection = {ContactsContract.PhoneLookup.NUMBER,
|
||||
ContactsContract.PhoneLookup._ID,
|
||||
ContactsContract.PhoneLookup.DISPLAY_NAME};
|
||||
@ -414,25 +405,21 @@ public class ContactsDatabase {
|
||||
numberCursor = context.getContentResolver().query(uri, projection, null, null, null);
|
||||
|
||||
while (numberCursor != null && numberCursor.moveToNext()) {
|
||||
try {
|
||||
String systemNumber = numberCursor.getString(0);
|
||||
String canonicalizedSystemNumber = PhoneNumberFormatter.formatNumber(systemNumber, localNumber);
|
||||
String systemNumber = numberCursor.getString(0);
|
||||
Address systemAddress = Address.fromExternal(context, systemNumber);
|
||||
|
||||
if (canonicalizedSystemNumber.equals(e164number)) {
|
||||
idCursor = context.getContentResolver().query(RawContacts.CONTENT_URI,
|
||||
new String[] {RawContacts._ID},
|
||||
RawContacts.CONTACT_ID + " = ? ",
|
||||
new String[] {String.valueOf(numberCursor.getLong(1))},
|
||||
null);
|
||||
if (systemAddress.equals(address)) {
|
||||
idCursor = context.getContentResolver().query(RawContacts.CONTENT_URI,
|
||||
new String[] {RawContacts._ID},
|
||||
RawContacts.CONTACT_ID + " = ? ",
|
||||
new String[] {String.valueOf(numberCursor.getLong(1))},
|
||||
null);
|
||||
|
||||
if (idCursor != null && idCursor.moveToNext()) {
|
||||
return Optional.of(new SystemContactInfo(numberCursor.getString(2),
|
||||
numberCursor.getString(0),
|
||||
idCursor.getLong(0)));
|
||||
}
|
||||
if (idCursor != null && idCursor.moveToNext()) {
|
||||
return Optional.of(new SystemContactInfo(numberCursor.getString(2),
|
||||
numberCursor.getString(0),
|
||||
idCursor.getLong(0)));
|
||||
}
|
||||
} catch (InvalidNumberException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
@ -7,6 +7,7 @@ import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.i18n.phonenumbers.NumberParseException;
|
||||
@ -20,7 +21,6 @@ import org.thoughtcrime.securesms.util.NumberUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
@ -60,7 +60,17 @@ public class Address implements Parcelable, Comparable<Address> {
|
||||
}
|
||||
|
||||
public static Address fromExternal(@NonNull Context context, @Nullable String external) {
|
||||
return new Address(new ExternalAddressFormatter(TextSecurePreferences.getLocalNumber(context)).format(external));
|
||||
String localNumber = TextSecurePreferences.getLocalNumber(context);
|
||||
|
||||
ExternalAddressFormatter formatter;
|
||||
|
||||
if (!TextUtils.isEmpty(localNumber)) {
|
||||
formatter = new ExternalAddressFormatter(localNumber);
|
||||
} else {
|
||||
formatter = new ExternalAddressFormatter(Util.getSimCountryIso(context).or("US"), true);
|
||||
}
|
||||
|
||||
return new Address(formatter.format(external));
|
||||
}
|
||||
|
||||
public static @NonNull List<Address> fromSerializedList(@NonNull String serialized, char delimiter) {
|
||||
@ -171,23 +181,28 @@ public class Address implements Parcelable, Comparable<Address> {
|
||||
add("AC");
|
||||
}};
|
||||
|
||||
private final Phonenumber.PhoneNumber localNumber;
|
||||
private final String localNumberString;
|
||||
private final String localCountryCode;
|
||||
private final String localNumberString;
|
||||
private final String localCountryCode;
|
||||
|
||||
private final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
|
||||
private final Pattern ALPHA_PATTERN = Pattern.compile("[a-zA-Z]");
|
||||
|
||||
public ExternalAddressFormatter(String localNumber) {
|
||||
ExternalAddressFormatter(@NonNull String localNumberString) {
|
||||
try {
|
||||
this.localNumberString = localNumber;
|
||||
this.localNumber = phoneNumberUtil.parse(localNumber, null);
|
||||
this.localCountryCode = phoneNumberUtil.getRegionCodeForNumber(this.localNumber);
|
||||
Phonenumber.PhoneNumber localNumber = phoneNumberUtil.parse(localNumberString, null);
|
||||
|
||||
this.localNumberString = localNumberString;
|
||||
this.localCountryCode = phoneNumberUtil.getRegionCodeForNumber(localNumber);
|
||||
} catch (NumberParseException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
ExternalAddressFormatter(@NonNull String localCountryCode, boolean countryCode) {
|
||||
this.localNumberString = "";
|
||||
this.localCountryCode = localCountryCode;
|
||||
}
|
||||
|
||||
public String format(@Nullable String number) {
|
||||
if (number == null) return "Unknown";
|
||||
if (number.startsWith("__textsecure_group__!")) return number;
|
||||
|
@ -8,11 +8,10 @@ import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.net.Uri;
|
||||
import android.provider.ContactsContract.CommonDataKinds.Phone;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import org.whispersystems.signalservice.api.push.ContactTokenDetails;
|
||||
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
||||
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@ -173,7 +172,7 @@ public class TextSecureDirectory {
|
||||
db.replace(TABLE_NAME, null, values);
|
||||
}
|
||||
|
||||
public void setNumbers(List<ContactTokenDetails> activeTokens, Collection<String> inactiveTokens) {
|
||||
public void setNumbers(List<ContactTokenDetails> activeTokens, Collection<Address> inactiveAddresses) {
|
||||
long timestamp = System.currentTimeMillis();
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
db.beginTransaction();
|
||||
@ -191,9 +190,9 @@ public class TextSecureDirectory {
|
||||
db.replace(TABLE_NAME, null, values);
|
||||
}
|
||||
|
||||
for (String token : inactiveTokens) {
|
||||
for (Address address : inactiveAddresses) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(NUMBER, token);
|
||||
values.put(NUMBER, address.serialize());
|
||||
values.put(REGISTERED, 0);
|
||||
values.put(TIMESTAMP, timestamp);
|
||||
db.replace(TABLE_NAME, null, values);
|
||||
@ -205,23 +204,18 @@ public class TextSecureDirectory {
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getPushEligibleContactNumbers(String localNumber) {
|
||||
final Uri uri = Phone.CONTENT_URI;
|
||||
final Set<String> results = new HashSet<>();
|
||||
Cursor cursor = null;
|
||||
public Set<Address> getPushEligibleContactNumbers() {
|
||||
final Uri uri = Phone.CONTENT_URI;
|
||||
final Set<Address> results = new HashSet<>();
|
||||
Cursor cursor = null;
|
||||
|
||||
try {
|
||||
cursor = context.getContentResolver().query(uri, new String[] {Phone.NUMBER}, null, null, null);
|
||||
|
||||
while (cursor != null && cursor.moveToNext()) {
|
||||
final String rawNumber = cursor.getString(0);
|
||||
if (rawNumber != null) {
|
||||
try {
|
||||
final String e164Number = PhoneNumberFormatter.formatNumber(rawNumber, localNumber);
|
||||
results.add(e164Number);
|
||||
} catch (InvalidNumberException e) {
|
||||
Log.w("Directory", "Invalid number: " + rawNumber);
|
||||
}
|
||||
if (!TextUtils.isEmpty(rawNumber)) {
|
||||
results.add(Address.fromExternal(context, rawNumber));
|
||||
}
|
||||
}
|
||||
|
||||
@ -234,7 +228,7 @@ public class TextSecureDirectory {
|
||||
null, null, null, null, null);
|
||||
|
||||
while (cursor != null && cursor.moveToNext()) {
|
||||
results.add(cursor.getString(0));
|
||||
results.add(Address.fromSerialized(cursor.getString(0)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ public class DirectoryRefreshJob extends ContextJob {
|
||||
if (recipients == null) {
|
||||
DirectoryHelper.refreshDirectory(context, KeyCachingService.getMasterSecret(context));
|
||||
} else {
|
||||
DirectoryHelper.refreshDirectoryFor(context, masterSecret, recipients, TextSecurePreferences.getLocalNumber(context));
|
||||
DirectoryHelper.refreshDirectoryFor(context, masterSecret, recipients);
|
||||
}
|
||||
SecurityEvent.broadcastSecurityUpdateEvent(context);
|
||||
} finally {
|
||||
|
@ -206,6 +206,7 @@ public class RegistrationService extends Service {
|
||||
String challenge = waitForChallenge();
|
||||
accountManager.verifyAccountWithCode(challenge, signalingKey, registrationId, !supportsGcm);
|
||||
|
||||
TextSecurePreferences.setLocalNumber(this, number);
|
||||
handleCommonRegistration(accountManager, number, password, signalingKey, supportsGcm);
|
||||
markAsVerified(number, password, signalingKey);
|
||||
|
||||
@ -257,7 +258,7 @@ public class RegistrationService extends Service {
|
||||
TextSecurePreferences.setWebsocketRegistered(this, true);
|
||||
|
||||
DatabaseFactory.getIdentityDatabase(this).saveIdentity(self, identityKey.getPublicKey(), IdentityDatabase.VerifiedStatus.VERIFIED, true, System.currentTimeMillis(), true);
|
||||
DirectoryHelper.refreshDirectory(this, accountManager, number);
|
||||
DirectoryHelper.refreshDirectory(this, accountManager);
|
||||
|
||||
DirectoryRefreshListener.schedule(this);
|
||||
RotateSignedPreKeyListener.schedule(this);
|
||||
|
@ -9,6 +9,7 @@ import android.os.RemoteException;
|
||||
import android.provider.ContactsContract;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
@ -32,6 +33,7 @@ import org.whispersystems.signalservice.api.push.ContactTokenDetails;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@ -75,9 +77,9 @@ public class DirectoryHelper {
|
||||
public static void refreshDirectory(@NonNull Context context, @Nullable MasterSecret masterSecret)
|
||||
throws IOException
|
||||
{
|
||||
RefreshResult result = refreshDirectory(context,
|
||||
AccountManagerFactory.createManager(context),
|
||||
TextSecurePreferences.getLocalNumber(context));
|
||||
if (TextUtils.isEmpty(TextSecurePreferences.getLocalNumber(context))) return;
|
||||
|
||||
RefreshResult result = refreshDirectory(context, AccountManagerFactory.createManager(context));
|
||||
|
||||
if (!result.getNewUsers().isEmpty() && TextSecurePreferences.isMultiDevice(context)) {
|
||||
ApplicationContext.getInstance(context)
|
||||
@ -90,32 +92,38 @@ public class DirectoryHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public static @NonNull RefreshResult refreshDirectory(@NonNull Context context,
|
||||
@NonNull SignalServiceAccountManager accountManager,
|
||||
@NonNull String localNumber)
|
||||
public static @NonNull RefreshResult refreshDirectory(@NonNull Context context, @NonNull SignalServiceAccountManager accountManager)
|
||||
throws IOException
|
||||
{
|
||||
TextSecureDirectory directory = TextSecureDirectory.getInstance(context);
|
||||
Set<String> eligibleContactNumbers = directory.getPushEligibleContactNumbers(localNumber);
|
||||
List<ContactTokenDetails> activeTokens = accountManager.getContacts(eligibleContactNumbers);
|
||||
if (TextUtils.isEmpty(TextSecurePreferences.getLocalNumber(context))) {
|
||||
return new RefreshResult(new LinkedList<Address>(), false);
|
||||
}
|
||||
|
||||
TextSecureDirectory directory = TextSecureDirectory.getInstance(context);
|
||||
Set<Address> eligibleContactNumbers = directory.getPushEligibleContactNumbers();
|
||||
Set<String> serializedAddresses = new HashSet<>();
|
||||
|
||||
for (Address address : eligibleContactNumbers) {
|
||||
serializedAddresses.add(address.serialize());
|
||||
}
|
||||
|
||||
List<ContactTokenDetails> activeTokens = accountManager.getContacts(serializedAddresses);
|
||||
|
||||
if (activeTokens != null) {
|
||||
for (ContactTokenDetails activeToken : activeTokens) {
|
||||
eligibleContactNumbers.remove(activeToken.getNumber());
|
||||
activeToken.setNumber(activeToken.getNumber());
|
||||
eligibleContactNumbers.remove(Address.fromSerialized(activeToken.getNumber()));
|
||||
}
|
||||
|
||||
directory.setNumbers(activeTokens, eligibleContactNumbers);
|
||||
return updateContactsDatabase(context, localNumber, activeTokens, true);
|
||||
return updateContactsDatabase(context, activeTokens, true);
|
||||
}
|
||||
|
||||
return new RefreshResult(new LinkedList<String>(), false);
|
||||
return new RefreshResult(new LinkedList<Address>(), false);
|
||||
}
|
||||
|
||||
public static UserCapabilities refreshDirectoryFor(@NonNull Context context,
|
||||
@Nullable MasterSecret masterSecret,
|
||||
@NonNull Recipients recipients,
|
||||
@NonNull String localNumber)
|
||||
@NonNull Recipients recipients)
|
||||
throws IOException
|
||||
{
|
||||
TextSecureDirectory directory = TextSecureDirectory.getInstance(context);
|
||||
@ -126,7 +134,7 @@ public class DirectoryHelper {
|
||||
if (details.isPresent()) {
|
||||
directory.setNumber(details.get(), true);
|
||||
|
||||
RefreshResult result = updateContactsDatabase(context, localNumber, details.get());
|
||||
RefreshResult result = updateContactsDatabase(context, details.get());
|
||||
|
||||
if (!result.getNewUsers().isEmpty() && TextSecurePreferences.isMultiDevice(context)) {
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new MultiDeviceContactUpdateJob(context));
|
||||
@ -181,16 +189,12 @@ public class DirectoryHelper {
|
||||
}
|
||||
|
||||
private static @NonNull RefreshResult updateContactsDatabase(@NonNull Context context,
|
||||
@NonNull String localNumber,
|
||||
@NonNull final ContactTokenDetails activeToken)
|
||||
{
|
||||
return updateContactsDatabase(context, localNumber,
|
||||
new LinkedList<ContactTokenDetails>() {{add(activeToken);}},
|
||||
false);
|
||||
return updateContactsDatabase(context, new LinkedList<ContactTokenDetails>() {{add(activeToken);}}, false);
|
||||
}
|
||||
|
||||
private static @NonNull RefreshResult updateContactsDatabase(@NonNull Context context,
|
||||
@NonNull String localNumber,
|
||||
@NonNull List<ContactTokenDetails> activeTokens,
|
||||
boolean removeMissing)
|
||||
{
|
||||
@ -198,8 +202,8 @@ public class DirectoryHelper {
|
||||
|
||||
if (account.isPresent()) {
|
||||
try {
|
||||
List<String> newUsers = DatabaseFactory.getContactsDatabase(context)
|
||||
.setRegisteredUsers(account.get().getAccount(), localNumber, activeTokens, removeMissing);
|
||||
List<Address> newUsers = DatabaseFactory.getContactsDatabase(context)
|
||||
.setRegisteredUsers(account.get().getAccount(), activeTokens, removeMissing);
|
||||
|
||||
return new RefreshResult(newUsers, account.get().isFresh());
|
||||
} catch (RemoteException | OperationApplicationException e) {
|
||||
@ -207,18 +211,16 @@ public class DirectoryHelper {
|
||||
}
|
||||
}
|
||||
|
||||
return new RefreshResult(new LinkedList<String>(), false);
|
||||
return new RefreshResult(new LinkedList<Address>(), false);
|
||||
}
|
||||
|
||||
private static void notifyNewUsers(@NonNull Context context,
|
||||
@Nullable MasterSecret masterSecret,
|
||||
@NonNull List<String> newUsers)
|
||||
@NonNull List<Address> newUsers)
|
||||
{
|
||||
if (!TextSecurePreferences.isNewContactsNotificationEnabled(context)) return;
|
||||
|
||||
for (String newUserString : newUsers) {
|
||||
Address newUser = Address.fromSerialized(newUserString);
|
||||
|
||||
for (Address newUser: newUsers) {
|
||||
if (!SessionUtil.hasSession(context, masterSecret, newUser) && !Util.isOwnNumber(context, newUser)) {
|
||||
IncomingJoinedMessage message = new IncomingJoinedMessage(newUser);
|
||||
Optional<InsertResult> insertResult = DatabaseFactory.getSmsDatabase(context).insertMessageInbox(message);
|
||||
@ -287,15 +289,15 @@ public class DirectoryHelper {
|
||||
|
||||
private static class RefreshResult {
|
||||
|
||||
private final List<String> newUsers;
|
||||
private final boolean fresh;
|
||||
private final List<Address> newUsers;
|
||||
private final boolean fresh;
|
||||
|
||||
private RefreshResult(List<String> newUsers, boolean fresh) {
|
||||
private RefreshResult(List<Address> newUsers, boolean fresh) {
|
||||
this.newUsers = newUsers;
|
||||
this.fresh = fresh;
|
||||
}
|
||||
|
||||
public List<String> getNewUsers() {
|
||||
public List<Address> getNewUsers() {
|
||||
return newUsers;
|
||||
}
|
||||
|
||||
|
@ -304,7 +304,7 @@ public class TextSecurePreferences {
|
||||
}
|
||||
|
||||
public static String getLocalNumber(Context context) {
|
||||
return getStringPreference(context, LOCAL_NUMBER_PREF, "No Stored Number");
|
||||
return getStringPreference(context, LOCAL_NUMBER_PREF, null);
|
||||
}
|
||||
|
||||
public static void setLocalNumber(Context context, String localNumber) {
|
||||
|
@ -42,11 +42,14 @@ import android.widget.EditText;
|
||||
|
||||
import com.google.android.mms.pdu_alt.CharacterSets;
|
||||
import com.google.android.mms.pdu_alt.EncodedStringValue;
|
||||
import com.google.i18n.phonenumbers.NumberParseException;
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
||||
import com.google.i18n.phonenumbers.Phonenumber;
|
||||
|
||||
import org.thoughtcrime.securesms.BuildConfig;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingLegacyMmsConnection;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@ -234,22 +237,24 @@ public class Util {
|
||||
return total;
|
||||
}
|
||||
|
||||
public static @Nullable String getDeviceE164Number(Context context) {
|
||||
final String localNumber = ((TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE)).getLine1Number();
|
||||
final String countryIso = getSimCountryIso(context);
|
||||
final Integer countryCode = PhoneNumberUtil.getInstance().getCountryCodeForRegion(countryIso);
|
||||
public static Optional<Phonenumber.PhoneNumber> getDeviceNumber(Context context) {
|
||||
try {
|
||||
final String localNumber = ((TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE)).getLine1Number();
|
||||
final Optional<String> countryIso = getSimCountryIso(context);
|
||||
|
||||
if (TextUtils.isEmpty(localNumber)) return null;
|
||||
if (TextUtils.isEmpty(localNumber)) return Optional.absent();
|
||||
if (!countryIso.isPresent()) return Optional.absent();
|
||||
|
||||
if (localNumber.startsWith("+")) return localNumber;
|
||||
else if (!TextUtils.isEmpty(countryIso)) return PhoneNumberFormatter.formatE164(String.valueOf(countryCode), localNumber);
|
||||
else if (localNumber.length() == 10) return "+1" + localNumber;
|
||||
else return "+" + localNumber;
|
||||
return Optional.fromNullable(PhoneNumberUtil.getInstance().parse(localNumber, countryIso.get()));
|
||||
} catch (NumberParseException e) {
|
||||
Log.w(TAG, e);
|
||||
return Optional.absent();
|
||||
}
|
||||
}
|
||||
|
||||
public static @Nullable String getSimCountryIso(Context context) {
|
||||
public static Optional<String> getSimCountryIso(Context context) {
|
||||
String simCountryIso = ((TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE)).getSimCountryIso();
|
||||
return simCountryIso != null ? simCountryIso.toUpperCase() : null;
|
||||
return Optional.fromNullable(simCountryIso != null ? simCountryIso.toUpperCase() : null);
|
||||
}
|
||||
|
||||
public static <T> List<List<T>> partition(List<T> list, int partitionSize) {
|
||||
|
@ -39,6 +39,9 @@ public class AddressTest {
|
||||
assertEquals(formatter.format("+1 415.111.1126"), "+14151111126");
|
||||
assertEquals(formatter.format("+1 415 111 1127"), "+14151111127");
|
||||
assertEquals(formatter.format("+1 (415) 111 1128"), "+14151111128");
|
||||
|
||||
formatter = new Address.ExternalAddressFormatter("+442079460010");
|
||||
assertEquals(formatter.format("(020) 7946 0018"), "+442079460018");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -47,4 +50,10 @@ public class AddressTest {
|
||||
assertEquals(formatter.format("__textsecure_group__!foobar"), "__textsecure_group__!foobar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLostLocalNumber() throws Exception {
|
||||
Address.ExternalAddressFormatter formatter = new Address.ExternalAddressFormatter("US", true);
|
||||
assertEquals(formatter.format("(415) 111-1122"), "+14151111122");
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user