kopia lustrzana https://github.com/ryukoposting/Signal-Android
Fix storage sync issue related to duplicate remote contacts.
The theory is that if multiple remote keys map to the *same* local entry, then when we go to update the local contact the second time, we won't find the entry by StorageID, because we changed it during the *first* update, which will then lead to a crash. This change makes it so dupes are considered invalid, so we'll delete them and upload our own local copy.fork-5.53.8
rodzic
904593c103
commit
857b945410
|
@ -7,6 +7,7 @@ import com.annimon.stream.Stream;
|
|||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.storage.SignalContactRecord;
|
||||
|
@ -15,9 +16,11 @@ import org.whispersystems.signalservice.internal.storage.protos.ContactRecord.Id
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
class ContactConflictMerger implements StorageSyncHelper.ConflictMerger<SignalContactRecord> {
|
||||
|
@ -52,11 +55,41 @@ class ContactConflictMerger implements StorageSyncHelper.ConflictMerger<SignalCo
|
|||
|
||||
@Override
|
||||
public @NonNull Collection<SignalContactRecord> getInvalidEntries(@NonNull Collection<SignalContactRecord> remoteRecords) {
|
||||
List<SignalContactRecord> invalid = Stream.of(remoteRecords)
|
||||
.filter(r -> r.getAddress().getUuid().equals(self.getUuid()) || r.getAddress().getNumber().equals(self.getE164()))
|
||||
.toList();
|
||||
Map<String, Set<SignalContactRecord>> localIdToRemoteRecords = new HashMap<>();
|
||||
|
||||
for (SignalContactRecord remote : remoteRecords) {
|
||||
Optional<SignalContactRecord> local = getMatching(remote);
|
||||
|
||||
if (local.isPresent()) {
|
||||
String serializedLocalId = Base64.encodeBytes(local.get().getId().getRaw());
|
||||
Set<SignalContactRecord> matches = localIdToRemoteRecords.get(serializedLocalId);
|
||||
|
||||
if (matches == null) {
|
||||
matches = new HashSet<>();
|
||||
}
|
||||
|
||||
matches.add(remote);
|
||||
localIdToRemoteRecords.put(serializedLocalId, matches);
|
||||
}
|
||||
}
|
||||
|
||||
Set<SignalContactRecord> duplicates = new HashSet<>();
|
||||
for (Set<SignalContactRecord> matches : localIdToRemoteRecords.values()) {
|
||||
if (matches.size() > 1) {
|
||||
duplicates.addAll(matches);
|
||||
}
|
||||
}
|
||||
|
||||
List<SignalContactRecord> selfRecords = Stream.of(remoteRecords)
|
||||
.filter(r -> r.getAddress().getUuid().equals(self.getUuid()) || r.getAddress().getNumber().equals(self.getE164()))
|
||||
.toList();
|
||||
|
||||
Set<SignalContactRecord> invalid = new HashSet<>();
|
||||
invalid.addAll(selfRecords);
|
||||
invalid.addAll(duplicates);
|
||||
|
||||
if (invalid.size() > 0) {
|
||||
Log.w(TAG, "Found invalid contact entries! Count: " + invalid.size());
|
||||
Log.w(TAG, "Found invalid contact entries! Self Records: " + selfRecords.size() + ", Duplicates: " + duplicates.size());
|
||||
}
|
||||
|
||||
return invalid;
|
||||
|
|
|
@ -150,6 +150,16 @@ public class ContactConflictMergerTest {
|
|||
assertEquals(local, merged);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInvalidEntries_nothingInvalid() {
|
||||
SignalContactRecord a = new SignalContactRecord.Builder(byteArray(1), new SignalServiceAddress(UUID_A, E164_A)).build();
|
||||
SignalContactRecord b = new SignalContactRecord.Builder(byteArray(2), new SignalServiceAddress(UUID_B, E164_B)).build();
|
||||
|
||||
Collection<SignalContactRecord> invalid = new ContactConflictMerger(Collections.emptyList(), SELF).getInvalidEntries(setOf(a, b));
|
||||
|
||||
assertContentsEqual(setOf(), invalid);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInvalidEntries_selfIsInvalid() {
|
||||
SignalContactRecord a = new SignalContactRecord.Builder(byteArray(1), new SignalServiceAddress(UUID_A, E164_A)).build();
|
||||
|
@ -160,4 +170,17 @@ public class ContactConflictMergerTest {
|
|||
|
||||
assertContentsEqual(setOf(self), invalid);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInvalidEntries_duplicatesInvalid() {
|
||||
SignalContactRecord aLocal = new SignalContactRecord.Builder(byteArray(1), new SignalServiceAddress(UUID_A, E164_A)).build();
|
||||
SignalContactRecord bRemote = new SignalContactRecord.Builder(byteArray(2), new SignalServiceAddress(UUID_B, E164_B)).build();
|
||||
SignalContactRecord aRemote1 = new SignalContactRecord.Builder(byteArray(3), new SignalServiceAddress(UUID_A, null)).build();
|
||||
SignalContactRecord aRemote2 = new SignalContactRecord.Builder(byteArray(4), new SignalServiceAddress(null, E164_A)).build();
|
||||
SignalContactRecord aRemote3 = new SignalContactRecord.Builder(byteArray(5), new SignalServiceAddress(UUID_A, E164_A)).build();
|
||||
|
||||
Collection<SignalContactRecord> invalid = new ContactConflictMerger(Collections.singleton(aLocal), SELF).getInvalidEntries(setOf(aRemote1, aRemote2, aRemote3, bRemote));
|
||||
|
||||
assertContentsEqual(setOf(aRemote1, aRemote2, aRemote3), invalid);
|
||||
}
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue