diff --git a/Signal/src/ViewControllers/DebugUI/DebugUISyncMessages.m b/Signal/src/ViewControllers/DebugUI/DebugUISyncMessages.m index 5e262248d..0d7be1d08 100644 --- a/Signal/src/ViewControllers/DebugUI/DebugUISyncMessages.m +++ b/Signal/src/ViewControllers/DebugUI/DebugUISyncMessages.m @@ -137,7 +137,7 @@ NS_ASSUME_NONNULL_BEGIN + (void)sendBlockListSyncMessage { - [self.blockingManager syncBlockedPhoneNumbers]; + [self.blockingManager syncBlockList]; } + (void)sendConfigurationSyncMessage diff --git a/SignalServiceKit/src/Devices/OWSBlockedPhoneNumbersMessage.h b/SignalServiceKit/src/Devices/OWSBlockedPhoneNumbersMessage.h index c4289893b..aefd4f831 100644 --- a/SignalServiceKit/src/Devices/OWSBlockedPhoneNumbersMessage.h +++ b/SignalServiceKit/src/Devices/OWSBlockedPhoneNumbersMessage.h @@ -10,7 +10,8 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithPhoneNumbers:(NSArray *)phoneNumbers NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithPhoneNumbers:(NSArray *)phoneNumbers + groupIds:(NSArray *)groupIds NS_DESIGNATED_INITIALIZER; - (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER; @end diff --git a/SignalServiceKit/src/Devices/OWSBlockedPhoneNumbersMessage.m b/SignalServiceKit/src/Devices/OWSBlockedPhoneNumbersMessage.m index f608eea91..d15f46e68 100644 --- a/SignalServiceKit/src/Devices/OWSBlockedPhoneNumbersMessage.m +++ b/SignalServiceKit/src/Devices/OWSBlockedPhoneNumbersMessage.m @@ -10,6 +10,7 @@ NS_ASSUME_NONNULL_BEGIN @interface OWSBlockedPhoneNumbersMessage () @property (nonatomic, readonly) NSArray *phoneNumbers; +@property (nonatomic, readonly) NSArray *groupIds; @end @@ -20,7 +21,7 @@ NS_ASSUME_NONNULL_BEGIN return [super initWithCoder:coder]; } -- (instancetype)initWithPhoneNumbers:(NSArray *)phoneNumbers +- (instancetype)initWithPhoneNumbers:(NSArray *)phoneNumbers groupIds:(NSArray *)groupIds { self = [super init]; if (!self) { @@ -28,6 +29,7 @@ NS_ASSUME_NONNULL_BEGIN } _phoneNumbers = [phoneNumbers copy]; + _groupIds = [groupIds copy]; return self; } @@ -36,6 +38,8 @@ NS_ASSUME_NONNULL_BEGIN { SSKProtoSyncMessageBlockedBuilder *blockedBuilder = [SSKProtoSyncMessageBlockedBuilder new]; [blockedBuilder setNumbers:_phoneNumbers]; + [blockedBuilder setGroupIds:_groupIds]; + NSError *error; SSKProtoSyncMessageBlocked *_Nullable blockedProto = [blockedBuilder buildAndReturnError:&error]; if (error || !blockedProto) { diff --git a/SignalServiceKit/src/Devices/OWSGroupsOutputStream.m b/SignalServiceKit/src/Devices/OWSGroupsOutputStream.m index c68ea4d7e..97f5fac36 100644 --- a/SignalServiceKit/src/Devices/OWSGroupsOutputStream.m +++ b/SignalServiceKit/src/Devices/OWSGroupsOutputStream.m @@ -4,6 +4,7 @@ #import "OWSGroupsOutputStream.h" #import "MIMETypeUtil.h" +#import "OWSBlockingManager.h" #import "OWSDisappearingMessagesConfiguration.h" #import "TSGroupModel.h" #import "TSGroupThread.h" @@ -27,6 +28,10 @@ NS_ASSUME_NONNULL_BEGIN [groupBuilder setMembers:group.groupMemberIds]; [groupBuilder setColor:groupThread.conversationColorName]; + if ([OWSBlockingManager.sharedManager isGroupIdBlocked:group.groupId]) { + [groupBuilder setBlocked:YES]; + } + NSData *avatarPng; if (group.groupImage) { SSKProtoGroupDetailsAvatarBuilder *avatarBuilder = diff --git a/SignalServiceKit/src/Messages/OWSBlockingManager.h b/SignalServiceKit/src/Messages/OWSBlockingManager.h index 1663a981d..57d7711d7 100644 --- a/SignalServiceKit/src/Messages/OWSBlockingManager.h +++ b/SignalServiceKit/src/Messages/OWSBlockingManager.h @@ -33,7 +33,7 @@ extern NSString *const kNSNotificationName_BlockedPhoneNumbersDidChange; - (BOOL)isRecipientIdBlocked:(NSString *)recipientId; - (BOOL)isThreadBlocked:(TSThread *)thread; -- (void)syncBlockedPhoneNumbers; +- (void)syncBlockList; @end diff --git a/SignalServiceKit/src/Messages/OWSBlockingManager.m b/SignalServiceKit/src/Messages/OWSBlockingManager.m index 243fc9fe8..24419fdf4 100644 --- a/SignalServiceKit/src/Messages/OWSBlockingManager.m +++ b/SignalServiceKit/src/Messages/OWSBlockingManager.m @@ -20,13 +20,13 @@ NSString *const kNSNotificationName_BlockedPhoneNumbersDidChange = @"kNSNotifica NSString *const kOWSBlockingManager_BlockListCollection = @"kOWSBlockingManager_BlockedPhoneNumbersCollection"; -// This key is used to persist the current "blocked phone numbers" state. +// These keys are used to persist the current local "block list" state. NSString *const kOWSBlockingManager_BlockedPhoneNumbersKey = @"kOWSBlockingManager_BlockedPhoneNumbersKey"; - NSString *const kOWSBlockingManager_BlockedGroupIdsKey = @"kOWSBlockingManager_BlockedGroupIdsKey"; -// This key is used to persist the most recently synced "blocked phone numbers" state. +// These keys are used to persist the most recently synced remote "block list" state. NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockingManager_SyncedBlockedPhoneNumbersKey"; +NSString *const kOWSBlockingManager_SyncedBlockedGroupIdsKey = @"kOWSBlockingManager_SyncedBlockedGroupIdsKey"; @interface OWSBlockingManager () @@ -264,6 +264,7 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin [self handleUpdate:YES]; } +// TODO label the `sendSyncMessage` param - (void)handleUpdate:(BOOL)sendSyncMessage { NSArray *blockedPhoneNumbers = [self blockedPhoneNumbers]; @@ -272,12 +273,18 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin forKey:kOWSBlockingManager_BlockedPhoneNumbersKey inCollection:kOWSBlockingManager_BlockListCollection]; + NSArray *blockedGroupIds = [self blockedGroupIds]; + + [self.dbConnection setObject:blockedGroupIds + forKey:kOWSBlockingManager_BlockedGroupIdsKey + inCollection:kOWSBlockingManager_BlockListCollection]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ if (sendSyncMessage) { - [self sendBlockedPhoneNumbersMessage:blockedPhoneNumbers]; + [self sendBlockListSyncMessageWithPhoneNumbers:blockedPhoneNumbers groupIds:blockedGroupIds]; } else { // If this update came from an incoming block list sync message, - // update the "synced blocked phone numbers" state immediately, + // update the "synced blocked list" state immediately, // since we're now in sync. // // There could be data loss if both clients modify the block list @@ -288,7 +295,7 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin // c) It's unlikely a user will make conflicting changes on two // devices around the same time. // d) There isn't a good way to avoid this. - [self saveSyncedBlockedPhoneNumbers:blockedPhoneNumbers]; + [self saveSyncedBlockListWithPhoneNumbers:blockedPhoneNumbers groupIds:blockedGroupIds]; } [[NSNotificationCenter defaultCenter] postNotificationNameAsync:kNSNotificationName_BlockedPhoneNumbersDidChange @@ -316,64 +323,82 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin inCollection:kOWSBlockingManager_BlockListCollection]; _blockedGroupIdSet = [[NSMutableSet alloc] initWithArray:(blockedGroupIds ?: [NSArray new])]; - [self syncBlockedPhoneNumbersIfNecessary]; + [self syncBlockListIfNecessary]; [self observeNotifications]; } -- (void)syncBlockedPhoneNumbers +- (void)syncBlockList { OWSAssert(_blockedPhoneNumberSet); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - [self sendBlockedPhoneNumbersMessage:self.blockedPhoneNumbers]; + [self sendBlockListSyncMessageWithPhoneNumbers:self.blockedPhoneNumbers groupIds:self.blockedGroupIds]; }); } // This method should only be called from within a synchronized block. -- (void)syncBlockedPhoneNumbersIfNecessary +- (void)syncBlockListIfNecessary { OWSAssert(_blockedPhoneNumberSet); - // If we haven't yet successfully synced the current "blocked phone numbers" changes, + // If we haven't yet successfully synced the current "block list" changes, // try again to sync now. NSArray *syncedBlockedPhoneNumbers = [self.dbConnection objectForKey:kOWSBlockingManager_SyncedBlockedPhoneNumbersKey inCollection:kOWSBlockingManager_BlockListCollection]; - NSSet *syncedBlockedPhoneNumberSet = [[NSSet alloc] initWithArray:(syncedBlockedPhoneNumbers ?: [NSArray new])]; - if (![_blockedPhoneNumberSet isEqualToSet:syncedBlockedPhoneNumberSet]) { - DDLogInfo(@"%@ retrying sync of blocked phone numbers", self.logTag); - [self sendBlockedPhoneNumbersMessage:self.blockedPhoneNumbers]; + NSSet *syncedBlockedPhoneNumberSet = + [[NSSet alloc] initWithArray:(syncedBlockedPhoneNumbers ?: [NSArray new])]; + + NSArray *syncedBlockedGroupIds = + [self.dbConnection objectForKey:kOWSBlockingManager_SyncedBlockedGroupIdsKey + inCollection:kOWSBlockingManager_BlockListCollection]; + NSSet *syncedBlockedGroupIdSet = [[NSSet alloc] initWithArray:(syncedBlockedGroupIds ?: [NSArray new])]; + + if ([self.blockedPhoneNumberSet isEqualToSet:syncedBlockedPhoneNumberSet] && + [self.blockedGroupIdSet isEqualToSet:syncedBlockedGroupIdSet]) { + DDLogVerbose(@"Ignoring redundant block list sync"); + return; } + + DDLogInfo(@"%@ retrying sync of block list", self.logTag); + [self sendBlockListSyncMessageWithPhoneNumbers:self.blockedPhoneNumbers groupIds:self.blockedGroupIds]; } -- (void)sendBlockedPhoneNumbersMessage:(NSArray *)blockedPhoneNumbers +- (void)sendBlockListSyncMessageWithPhoneNumbers:(NSArray *)blockedPhoneNumbers + groupIds:(NSArray *)blockedGroupIds { OWSAssert(blockedPhoneNumbers); OWSAssert(blockedGroupIds); OWSBlockedPhoneNumbersMessage *message = - [[OWSBlockedPhoneNumbersMessage alloc] initWithPhoneNumbers:blockedPhoneNumbers]; + [[OWSBlockedPhoneNumbersMessage alloc] initWithPhoneNumbers:blockedPhoneNumbers groupIds:blockedGroupIds]; [self.messageSender enqueueMessage:message success:^{ DDLogInfo(@"%@ Successfully sent blocked phone numbers sync message", self.logTag); // Record the last set of "blocked phone numbers" which we successfully synced. - [self saveSyncedBlockedPhoneNumbers:blockedPhoneNumbers]; + [self saveSyncedBlockListWithPhoneNumbers:blockedPhoneNumbers groupIds:blockedGroupIds]; } failure:^(NSError *error) { DDLogError(@"%@ Failed to send blocked phone numbers sync message with error: %@", self.logTag, error); }]; } -- (void)saveSyncedBlockedPhoneNumbers:(NSArray *)blockedPhoneNumbers +/// Records the last block list which we successfully synced. +- (void)saveSyncedBlockListWithPhoneNumbers:(NSArray *)blockedPhoneNumbers + groupIds:(NSArray *)blockedGroupIds { OWSAssert(blockedPhoneNumbers); + OWSAssert(blockedGroupIds); - // Record the last set of "blocked phone numbers" which we successfully synced. [self.dbConnection setObject:blockedPhoneNumbers forKey:kOWSBlockingManager_SyncedBlockedPhoneNumbersKey inCollection:kOWSBlockingManager_BlockListCollection]; + + [self.dbConnection setObject:blockedGroupIds + forKey:kOWSBlockingManager_SyncedBlockedGroupIdsKey + inCollection:kOWSBlockingManager_BlockListCollection]; } #pragma mark - Notifications @@ -385,7 +410,7 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin [AppReadiness runNowOrWhenAppIsReady:^{ @synchronized(self) { - [self syncBlockedPhoneNumbersIfNecessary]; + [self syncBlockListIfNecessary]; } }]; } diff --git a/SignalServiceKit/src/Messages/OWSMessageManager.m b/SignalServiceKit/src/Messages/OWSMessageManager.m index f87fb9ec3..8358d6475 100644 --- a/SignalServiceKit/src/Messages/OWSMessageManager.m +++ b/SignalServiceKit/src/Messages/OWSMessageManager.m @@ -698,7 +698,7 @@ NS_ASSUME_NONNULL_BEGIN }]; } else if (syncMessage.request.type == SSKProtoSyncMessageRequestTypeBlocked) { DDLogInfo(@"%@ Received request for block list", self.logTag); - [_blockingManager syncBlockedPhoneNumbers]; + [_blockingManager syncBlockList]; } else if (syncMessage.request.type == SSKProtoSyncMessageRequestTypeConfiguration) { BOOL areReadReceiptsEnabled = [[OWSReadReceiptManager sharedManager] areReadReceiptsEnabledWithTransaction:transaction];