Search in sources :

Example 61 with RecipientDatabase

use of org.thoughtcrime.securesms.database.RecipientDatabase in project Signal-Android by signalapp.

the class StorageSyncJob method buildLocalStorageRecords.

@NonNull
private static List<SignalStorageRecord> buildLocalStorageRecords(@NonNull Context context, @NonNull Recipient self, @NonNull Collection<StorageId> ids) {
    if (ids.isEmpty()) {
        return Collections.emptyList();
    }
    RecipientDatabase recipientDatabase = SignalDatabase.recipients();
    UnknownStorageIdDatabase storageIdDatabase = SignalDatabase.unknownStorageIds();
    List<SignalStorageRecord> records = new ArrayList<>(ids.size());
    for (StorageId id : ids) {
        switch(id.getType()) {
            case ManifestRecord.Identifier.Type.CONTACT_VALUE:
            case ManifestRecord.Identifier.Type.GROUPV1_VALUE:
            case ManifestRecord.Identifier.Type.GROUPV2_VALUE:
                RecipientRecord settings = recipientDatabase.getByStorageId(id.getRaw());
                if (settings != null) {
                    if (settings.getGroupType() == RecipientDatabase.GroupType.SIGNAL_V2 && settings.getSyncExtras().getGroupMasterKey() == null) {
                        throw new MissingGv2MasterKeyError();
                    } else {
                        records.add(StorageSyncModels.localToRemoteRecord(settings));
                    }
                } else {
                    throw new MissingRecipientModelError("Missing local recipient model! Type: " + id.getType());
                }
                break;
            case ManifestRecord.Identifier.Type.ACCOUNT_VALUE:
                if (!Arrays.equals(self.getStorageServiceId(), id.getRaw())) {
                    throw new AssertionError("Local storage ID doesn't match self!");
                }
                records.add(StorageSyncHelper.buildAccountRecord(context, self));
                break;
            default:
                SignalStorageRecord unknown = storageIdDatabase.getById(id.getRaw());
                if (unknown != null) {
                    records.add(unknown);
                } else {
                    throw new MissingUnknownModelError("Missing local unknown model! Type: " + id.getType());
                }
                break;
        }
    }
    return records;
}
Also used : RecipientDatabase(org.thoughtcrime.securesms.database.RecipientDatabase) RecipientRecord(org.thoughtcrime.securesms.database.model.RecipientRecord) ArrayList(java.util.ArrayList) SignalStorageRecord(org.whispersystems.signalservice.api.storage.SignalStorageRecord) UnknownStorageIdDatabase(org.thoughtcrime.securesms.database.UnknownStorageIdDatabase) StorageId(org.whispersystems.signalservice.api.storage.StorageId) NonNull(androidx.annotation.NonNull)

Example 62 with RecipientDatabase

use of org.thoughtcrime.securesms.database.RecipientDatabase in project Signal-Android by signalapp.

the class MessageContentProcessor method handleProfileKey.

private void handleProfileKey(@NonNull SignalServiceContent content, @NonNull byte[] messageProfileKeyBytes, @NonNull Recipient senderRecipient) {
    RecipientDatabase database = SignalDatabase.recipients();
    ProfileKey messageProfileKey = ProfileKeyUtil.profileKeyOrNull(messageProfileKeyBytes);
    if (senderRecipient.isSelf()) {
        if (!Objects.equals(ProfileKeyUtil.getSelfProfileKey(), messageProfileKey)) {
            warn(content.getTimestamp(), "Saw a sync message whose profile key doesn't match our records. Scheduling a storage sync to check.");
            StorageSyncHelper.scheduleSyncForDataChange();
        }
    } else if (messageProfileKey != null) {
        if (database.setProfileKey(senderRecipient.getId(), messageProfileKey)) {
            log(content.getTimestamp(), "Profile key on message from " + senderRecipient.getId() + " didn't match our local store. It has been updated.");
            ApplicationDependencies.getJobManager().add(RetrieveProfileJob.forRecipient(senderRecipient.getId()));
        }
    } else {
        warn(String.valueOf(content.getTimestamp()), "Ignored invalid profile key seen in message");
    }
}
Also used : RecipientDatabase(org.thoughtcrime.securesms.database.RecipientDatabase) ProfileKey(org.signal.zkgroup.profiles.ProfileKey)

Example 63 with RecipientDatabase

use of org.thoughtcrime.securesms.database.RecipientDatabase in project Signal-Android by signalapp.

the class MessageContentProcessor method handleSynchronizeMessageRequestResponse.

private void handleSynchronizeMessageRequestResponse(@NonNull MessageRequestResponseMessage response, long envelopeTimestamp) throws BadGroupIdException {
    log(envelopeTimestamp, "Synchronize message request response.");
    RecipientDatabase recipientDatabase = SignalDatabase.recipients();
    ThreadDatabase threadDatabase = SignalDatabase.threads();
    Recipient recipient;
    if (response.getPerson().isPresent()) {
        recipient = Recipient.externalPush(response.getPerson().get());
    } else if (response.getGroupId().isPresent()) {
        GroupId groupId = GroupId.v1(response.getGroupId().get());
        recipient = Recipient.externalPossiblyMigratedGroup(context, groupId);
    } else {
        warn("Message request response was missing a thread recipient! Skipping.");
        return;
    }
    long threadId = threadDatabase.getOrCreateThreadIdFor(recipient);
    switch(response.getType()) {
        case ACCEPT:
            recipientDatabase.setProfileSharing(recipient.getId(), true);
            recipientDatabase.setBlocked(recipient.getId(), false);
            break;
        case DELETE:
            recipientDatabase.setProfileSharing(recipient.getId(), false);
            if (threadId > 0)
                threadDatabase.deleteConversation(threadId);
            break;
        case BLOCK:
            recipientDatabase.setBlocked(recipient.getId(), true);
            recipientDatabase.setProfileSharing(recipient.getId(), false);
            break;
        case BLOCK_AND_DELETE:
            recipientDatabase.setBlocked(recipient.getId(), true);
            recipientDatabase.setProfileSharing(recipient.getId(), false);
            if (threadId > 0)
                threadDatabase.deleteConversation(threadId);
            break;
        default:
            warn("Got an unknown response type! Skipping");
            break;
    }
}
Also used : RecipientDatabase(org.thoughtcrime.securesms.database.RecipientDatabase) Recipient(org.thoughtcrime.securesms.recipients.Recipient) ThreadDatabase(org.thoughtcrime.securesms.database.ThreadDatabase) GroupId(org.thoughtcrime.securesms.groups.GroupId)

Example 64 with RecipientDatabase

use of org.thoughtcrime.securesms.database.RecipientDatabase in project Signal-Android by signalapp.

the class MessageRequestRepository method acceptMessageRequest.

void acceptMessageRequest(@NonNull LiveRecipient liveRecipient, long threadId, @NonNull Runnable onMessageRequestAccepted, @NonNull GroupChangeErrorCallback error) {
    executor.execute(() -> {
        if (liveRecipient.get().isPushV2Group()) {
            try {
                Log.i(TAG, "GV2 accepting invite");
                GroupManager.acceptInvite(context, liveRecipient.get().requireGroupId().requireV2());
                RecipientDatabase recipientDatabase = SignalDatabase.recipients();
                recipientDatabase.setProfileSharing(liveRecipient.getId(), true);
                onMessageRequestAccepted.run();
            } catch (GroupChangeException | IOException e) {
                Log.w(TAG, e);
                error.onError(GroupChangeFailureReason.fromException(e));
            }
        } else {
            RecipientDatabase recipientDatabase = SignalDatabase.recipients();
            recipientDatabase.setProfileSharing(liveRecipient.getId(), true);
            MessageSender.sendProfileKey(context, threadId);
            List<MessageDatabase.MarkedMessageInfo> messageIds = SignalDatabase.threads().setEntireThreadRead(threadId);
            ApplicationDependencies.getMessageNotifier().updateNotification(context);
            MarkReadReceiver.process(context, messageIds);
            List<MessageDatabase.MarkedMessageInfo> viewedInfos = SignalDatabase.mms().getViewedIncomingMessages(threadId);
            SendViewedReceiptJob.enqueue(threadId, liveRecipient.getId(), viewedInfos);
            if (TextSecurePreferences.isMultiDevice(context)) {
                ApplicationDependencies.getJobManager().add(MultiDeviceMessageRequestResponseJob.forAccept(liveRecipient.getId()));
            }
            onMessageRequestAccepted.run();
        }
    });
}
Also used : RecipientDatabase(org.thoughtcrime.securesms.database.RecipientDatabase) GroupChangeException(org.thoughtcrime.securesms.groups.GroupChangeException) IOException(java.io.IOException)

Example 65 with RecipientDatabase

use of org.thoughtcrime.securesms.database.RecipientDatabase in project Signal-Android by signalapp.

the class NotificationChannels method ensureCustomChannelConsistency.

@TargetApi(26)
@WorkerThread
public static synchronized void ensureCustomChannelConsistency(@NonNull Context context) {
    if (!supported()) {
        return;
    }
    Log.d(TAG, "ensureCustomChannelConsistency()");
    NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
    RecipientDatabase db = SignalDatabase.recipients();
    List<Recipient> customRecipients = new ArrayList<>();
    Set<String> customChannelIds = new HashSet<>();
    try (RecipientDatabase.RecipientReader reader = db.getRecipientsWithNotificationChannels()) {
        Recipient recipient;
        while ((recipient = reader.getNext()) != null) {
            customRecipients.add(recipient);
            customChannelIds.add(recipient.getNotificationChannel());
        }
    }
    Set<String> existingChannelIds = Stream.of(notificationManager.getNotificationChannels()).map(NotificationChannel::getId).collect(Collectors.toSet());
    for (NotificationChannel existingChannel : notificationManager.getNotificationChannels()) {
        if ((existingChannel.getId().startsWith(CONTACT_PREFIX) || existingChannel.getId().startsWith(MESSAGES_PREFIX)) && Build.VERSION.SDK_INT >= CONVERSATION_SUPPORT_VERSION && existingChannel.getConversationId() != null) {
            if (customChannelIds.contains(existingChannel.getId())) {
                continue;
            }
            RecipientId id = ConversationUtil.getRecipientId(existingChannel.getConversationId());
            if (id != null) {
                Log.i(TAG, "Consistency: Conversation channel created outside of app, update " + id + " to use '" + existingChannel.getId() + "'");
                db.setNotificationChannel(id, existingChannel.getId());
            } else {
                Log.i(TAG, "Consistency: Conversation channel created outside of app with no matching recipient, deleting channel '" + existingChannel.getId() + "'");
                notificationManager.deleteNotificationChannel(existingChannel.getId());
            }
        } else if (existingChannel.getId().startsWith(CONTACT_PREFIX) && !customChannelIds.contains(existingChannel.getId())) {
            Log.i(TAG, "Consistency: Deleting channel '" + existingChannel.getId() + "' because the DB has no record of it.");
            notificationManager.deleteNotificationChannel(existingChannel.getId());
        } else if (existingChannel.getId().startsWith(MESSAGES_PREFIX) && !existingChannel.getId().equals(getMessagesChannel(context))) {
            Log.i(TAG, "Consistency: Deleting channel '" + existingChannel.getId() + "' because it's out of date.");
            notificationManager.deleteNotificationChannel(existingChannel.getId());
        }
    }
    for (Recipient customRecipient : customRecipients) {
        if (!existingChannelIds.contains(customRecipient.getNotificationChannel())) {
            Log.i(TAG, "Consistency: Removing custom channel '" + customRecipient.getNotificationChannel() + "' because the system doesn't have it.");
            db.setNotificationChannel(customRecipient.getId(), null);
        }
    }
}
Also used : NotificationChannel(android.app.NotificationChannel) RecipientDatabase(org.thoughtcrime.securesms.database.RecipientDatabase) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) NotificationManager(android.app.NotificationManager) ArrayList(java.util.ArrayList) Recipient(org.thoughtcrime.securesms.recipients.Recipient) HashSet(java.util.HashSet) WorkerThread(androidx.annotation.WorkerThread) TargetApi(android.annotation.TargetApi)

Aggregations

RecipientDatabase (org.thoughtcrime.securesms.database.RecipientDatabase)72 Recipient (org.thoughtcrime.securesms.recipients.Recipient)32 WorkerThread (androidx.annotation.WorkerThread)30 RecipientId (org.thoughtcrime.securesms.recipients.RecipientId)20 NonNull (androidx.annotation.NonNull)18 IOException (java.io.IOException)14 Nullable (androidx.annotation.Nullable)10 ArrayList (java.util.ArrayList)10 Log (org.signal.core.util.logging.Log)10 SignalDatabase (org.thoughtcrime.securesms.database.SignalDatabase)10 ACI (org.whispersystems.signalservice.api.push.ACI)10 Context (android.content.Context)8 Stream (com.annimon.stream.Stream)8 Collections (java.util.Collections)8 List (java.util.List)8 TimeUnit (java.util.concurrent.TimeUnit)8 ProfileKey (org.signal.zkgroup.profiles.ProfileKey)8 ApplicationDependencies (org.thoughtcrime.securesms.dependencies.ApplicationDependencies)8 Optional (org.whispersystems.libsignal.util.guava.Optional)8 HashSet (java.util.HashSet)7