From eed637791042089cf3832d097b81c4e6647c01d6 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 7 Jun 2017 15:00:11 -0400 Subject: [PATCH 1/4] Add verification state change messages. // FREEBIE --- .../OWSVerificationStateChangeMessage.h | 21 ++++++++ .../OWSVerificationStateChangeMessage.m | 52 +++++++++++++++++++ src/Messages/Interactions/TSInfoMessage.h | 1 + 3 files changed, 74 insertions(+) create mode 100644 src/Messages/Interactions/OWSVerificationStateChangeMessage.h create mode 100644 src/Messages/Interactions/OWSVerificationStateChangeMessage.m diff --git a/src/Messages/Interactions/OWSVerificationStateChangeMessage.h b/src/Messages/Interactions/OWSVerificationStateChangeMessage.h new file mode 100644 index 000000000..2951297a4 --- /dev/null +++ b/src/Messages/Interactions/OWSVerificationStateChangeMessage.h @@ -0,0 +1,21 @@ +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// + +#import "OWSRecipientIdentity.h" +#import "TSInfoMessage.h" + +NS_ASSUME_NONNULL_BEGIN + +@class TSThread; + +@interface OWSVerificationStateChangeMessage : TSInfoMessage + +- (instancetype)initWithTimestamp:(uint64_t)timestamp + thread:(TSThread *)thread + verificationState:(OWSVerificationState)verificationState + isLocalChange:(BOOL)isLocalChange; + +@end + +NS_ASSUME_NONNULL_END diff --git a/src/Messages/Interactions/OWSVerificationStateChangeMessage.m b/src/Messages/Interactions/OWSVerificationStateChangeMessage.m new file mode 100644 index 000000000..f8bdcb48d --- /dev/null +++ b/src/Messages/Interactions/OWSVerificationStateChangeMessage.m @@ -0,0 +1,52 @@ +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// + +#import "OWSVerificationStateChangeMessage.h" +#import "OWSDisappearingMessagesConfiguration.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface OWSVerificationStateChangeMessage () + +@property (nonatomic, readonly) OWSVerificationState verificationState; +@property (nonatomic, readonly) BOOL isLocalChange; + +@end + +#pragma mark - + +@implementation OWSVerificationStateChangeMessage + +- (instancetype)initWithTimestamp:(uint64_t)timestamp + thread:(TSThread *)thread + verificationState:(OWSVerificationState)verificationState + isLocalChange:(BOOL)isLocalChange +{ + self = [super initWithTimestamp:timestamp inThread:thread messageType:TSInfoMessageVerificationStateChange]; + if (!self) { + return self; + } + + _verificationState = verificationState; + _isLocalChange = isLocalChange; + + return self; +} + +- (NSString *)description +{ + switch (self.verificationState) { + case OWSVerificationStateDefault: + case OWSVerificationStateNoLongerVerified: + return NSLocalizedString(@"VERIFICATION_STATE_CHANGE_NOT_VERIFIED", + @"Info Message indicating that the verification state is not verified."); + case OWSVerificationStateVerified: + return NSLocalizedString(@"VERIFICATION_STATE_CHANGE_VERIFIED", + @"Info Message indicating that the verification state is verified."); + } +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/src/Messages/Interactions/TSInfoMessage.h b/src/Messages/Interactions/TSInfoMessage.h index 7ee7c924a..4bd00c871 100644 --- a/src/Messages/Interactions/TSInfoMessage.h +++ b/src/Messages/Interactions/TSInfoMessage.h @@ -18,6 +18,7 @@ typedef NS_ENUM(NSInteger, TSInfoMessageType) { TSInfoMessageTypeGroupQuit, TSInfoMessageTypeDisappearingMessagesUpdate, TSInfoMessageAddToContactsOffer, + TSInfoMessageVerificationStateChange, }; + (instancetype)userNotRegisteredMessageInThread:(TSThread *)thread; From fdd172bda337639c29eda6348e13ae2b688b9c8b Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 7 Jun 2017 16:51:17 -0400 Subject: [PATCH 2/4] Add verification state change messages. // FREEBIE --- .../OWSVerificationStateChangeMessage.h | 5 ++ .../OWSVerificationStateChangeMessage.m | 29 ++------ src/Messages/OWSIdentityManager.h | 2 + src/Messages/OWSIdentityManager.m | 72 ++++++++++++++++++- 4 files changed, 82 insertions(+), 26 deletions(-) diff --git a/src/Messages/Interactions/OWSVerificationStateChangeMessage.h b/src/Messages/Interactions/OWSVerificationStateChangeMessage.h index 2951297a4..2f1a3f75a 100644 --- a/src/Messages/Interactions/OWSVerificationStateChangeMessage.h +++ b/src/Messages/Interactions/OWSVerificationStateChangeMessage.h @@ -11,8 +11,13 @@ NS_ASSUME_NONNULL_BEGIN @interface OWSVerificationStateChangeMessage : TSInfoMessage +@property (nonatomic, readonly) NSString *recipientId; +@property (nonatomic, readonly) OWSVerificationState verificationState; +@property (nonatomic, readonly) BOOL isLocalChange; + - (instancetype)initWithTimestamp:(uint64_t)timestamp thread:(TSThread *)thread + recipientId:(NSString *)recipientId verificationState:(OWSVerificationState)verificationState isLocalChange:(BOOL)isLocalChange; diff --git a/src/Messages/Interactions/OWSVerificationStateChangeMessage.m b/src/Messages/Interactions/OWSVerificationStateChangeMessage.m index f8bdcb48d..ff46c791d 100644 --- a/src/Messages/Interactions/OWSVerificationStateChangeMessage.m +++ b/src/Messages/Interactions/OWSVerificationStateChangeMessage.m @@ -7,46 +7,29 @@ NS_ASSUME_NONNULL_BEGIN -@interface OWSVerificationStateChangeMessage () - -@property (nonatomic, readonly) OWSVerificationState verificationState; -@property (nonatomic, readonly) BOOL isLocalChange; - -@end - -#pragma mark - - @implementation OWSVerificationStateChangeMessage - (instancetype)initWithTimestamp:(uint64_t)timestamp thread:(TSThread *)thread + recipientId:(NSString *)recipientId verificationState:(OWSVerificationState)verificationState isLocalChange:(BOOL)isLocalChange { - self = [super initWithTimestamp:timestamp inThread:thread messageType:TSInfoMessageVerificationStateChange]; + OWSAssert(recipientId.length > 0) + + self + = [super initWithTimestamp:timestamp inThread:thread messageType:TSInfoMessageVerificationStateChange]; if (!self) { return self; } + _recipientId = recipientId; _verificationState = verificationState; _isLocalChange = isLocalChange; return self; } -- (NSString *)description -{ - switch (self.verificationState) { - case OWSVerificationStateDefault: - case OWSVerificationStateNoLongerVerified: - return NSLocalizedString(@"VERIFICATION_STATE_CHANGE_NOT_VERIFIED", - @"Info Message indicating that the verification state is not verified."); - case OWSVerificationStateVerified: - return NSLocalizedString(@"VERIFICATION_STATE_CHANGE_VERIFIED", - @"Info Message indicating that the verification state is verified."); - } -} - @end NS_ASSUME_NONNULL_END diff --git a/src/Messages/OWSIdentityManager.h b/src/Messages/OWSIdentityManager.h index 17f31ddd7..d5d8afc98 100644 --- a/src/Messages/OWSIdentityManager.h +++ b/src/Messages/OWSIdentityManager.h @@ -37,6 +37,8 @@ extern const NSUInteger kIdentityKeyLength; - (OWSVerificationState)verificationStateForRecipientId:(NSString *)recipientId; +- (nullable OWSRecipientIdentity *)recipientIdentityForRecipientId:(NSString *)recipientId; + /** * @param recipientId unique stable identifier for the recipient, e.g. e164 phone number * @returns nil if the recipient does not exist, or is trusted for sending diff --git a/src/Messages/OWSIdentityManager.m b/src/Messages/OWSIdentityManager.m index d94057d72..6dd8943fe 100644 --- a/src/Messages/OWSIdentityManager.m +++ b/src/Messages/OWSIdentityManager.m @@ -3,9 +3,11 @@ // #import "OWSIdentityManager.h" +#import "NSDate+millisecondTimeStamp.h" #import "NotificationsProtocol.h" #import "OWSMessageSender.h" #import "OWSRecipientIdentity.h" +#import "OWSVerificationStateChangeMessage.h" #import "OWSVerificationStateSyncMessage.h" #import "TSAccountManager.h" #import "TSContactThread.h" @@ -190,6 +192,14 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa // Cancel any pending verification state sync messages for this recipient. [self clearSyncMessageForRecipientId:recipientId]; + // TODO: This may be redundant with the "safety number changes" + // messages. + if (existingIdentity.verificationState != verificationState) { + [self saveChangeMessagesForRecipientId:recipientId + verificationState:verificationState + isLocalChange:YES]; + } + [self fireIdentityStateChangeNotification]; return YES; @@ -241,6 +251,8 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa // Cancel any pending verification state sync messages for this recipient. [self clearSyncMessageForRecipientId:recipientId]; } + + [self saveChangeMessagesForRecipientId:recipientId verificationState:verificationState isLocalChange:YES]; } [self fireIdentityStateChangeNotification]; @@ -263,6 +275,16 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa } } +- (nullable OWSRecipientIdentity *)recipientIdentityForRecipientId:(NSString *)recipientId +{ + OWSAssert(recipientId.length > 0); + + @synchronized(self) + { + return [OWSRecipientIdentity fetchObjectWithUniqueID:recipientId]; + } +} + - (nullable OWSRecipientIdentity *)untrustedIdentityForSendingToRecipientId:(NSString *)recipientId { OWSAssert(recipientId.length > 0); @@ -385,18 +407,25 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa { OWSAssert(recipientId != nil); + NSMutableArray *messages = [NSMutableArray new]; + TSContactThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:recipientId]; OWSAssert(contactThread != nil); TSErrorMessage *errorMessage = [TSErrorMessage nonblockingIdentityChangeInThread:contactThread recipientId:recipientId]; - [errorMessage save]; - + [messages addObject:errorMessage]; [[TextSecureKitEnv sharedEnv].notificationsManager notifyUserForErrorMessage:errorMessage inThread:contactThread]; for (TSGroupThread *groupThread in [TSGroupThread groupThreadsWithRecipientId:recipientId]) { - [[TSErrorMessage nonblockingIdentityChangeInThread:groupThread recipientId:recipientId] save]; + [messages addObject:[TSErrorMessage nonblockingIdentityChangeInThread:groupThread recipientId:recipientId]]; } + + [self.storageManager.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + for (TSMessage *message in messages) { + [message saveWithTransaction:transaction]; + } + }]; } - (void)enqueueSyncMessageForVerificationState:(OWSVerificationState)verificationState @@ -625,6 +654,9 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa OWSVerificationStateToString(verificationState)); [recipientIdentity updateWithVerificationState:verificationState]; + + // No need to call [saveChangeMessagesForRecipientId:..] since this is + // a new recipient. } else { // There's an existing recipient identity for this recipient. // We should update it. @@ -668,10 +700,44 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa } [recipientIdentity updateWithVerificationState:verificationState]; + + [self saveChangeMessagesForRecipientId:recipientId verificationState:verificationState isLocalChange:NO]; } } } +- (void)saveChangeMessagesForRecipientId:(NSString *)recipientId + verificationState:(OWSVerificationState)verificationState + isLocalChange:(BOOL)isLocalChange +{ + OWSAssert(recipientId.length > 0); + + NSMutableArray *messages = [NSMutableArray new]; + + TSContactThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:recipientId]; + OWSAssert(contactThread); + [messages addObject:[[OWSVerificationStateChangeMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] + thread:contactThread + recipientId:recipientId + verificationState:verificationState + isLocalChange:isLocalChange]]; + + for (TSGroupThread *groupThread in [TSGroupThread groupThreadsWithRecipientId:recipientId]) { + [messages + addObject:[[OWSVerificationStateChangeMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] + thread:groupThread + recipientId:recipientId + verificationState:verificationState + isLocalChange:isLocalChange]]; + } + + [self.storageManager.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + for (TSMessage *message in messages) { + [message saveWithTransaction:transaction]; + } + }]; +} + #pragma mark - Notifications - (void)applicationDidBecomeActive:(NSNotification *)notification From 841271dc6cbcda241cdc95ab58026f54bad89a8a Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Thu, 8 Jun 2017 10:34:32 -0400 Subject: [PATCH 3/4] Respond to CR. // FREEBIE --- .../Interactions/OWSVerificationStateChangeMessage.m | 5 ++--- src/Messages/OWSIdentityManager.m | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Messages/Interactions/OWSVerificationStateChangeMessage.m b/src/Messages/Interactions/OWSVerificationStateChangeMessage.m index ff46c791d..8b82f51b2 100644 --- a/src/Messages/Interactions/OWSVerificationStateChangeMessage.m +++ b/src/Messages/Interactions/OWSVerificationStateChangeMessage.m @@ -15,10 +15,9 @@ NS_ASSUME_NONNULL_BEGIN verificationState:(OWSVerificationState)verificationState isLocalChange:(BOOL)isLocalChange { - OWSAssert(recipientId.length > 0) + OWSAssert(recipientId.length > 0); - self - = [super initWithTimestamp:timestamp inThread:thread messageType:TSInfoMessageVerificationStateChange]; + self = [super initWithTimestamp:timestamp inThread:thread messageType:TSInfoMessageVerificationStateChange]; if (!self) { return self; } diff --git a/src/Messages/OWSIdentityManager.m b/src/Messages/OWSIdentityManager.m index 6dd8943fe..2856e1039 100644 --- a/src/Messages/OWSIdentityManager.m +++ b/src/Messages/OWSIdentityManager.m @@ -192,8 +192,6 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa // Cancel any pending verification state sync messages for this recipient. [self clearSyncMessageForRecipientId:recipientId]; - // TODO: This may be redundant with the "safety number changes" - // messages. if (existingIdentity.verificationState != verificationState) { [self saveChangeMessagesForRecipientId:recipientId verificationState:verificationState From ca04d912db4fbe777bb99ed8e8e7e0d1df9dc69d Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Thu, 8 Jun 2017 10:39:27 -0400 Subject: [PATCH 4/4] Don't actually transmit any verification state sync messages until we finalize the proto schema changes. // FREEBIE --- src/Messages/OWSIdentityManager.m | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Messages/OWSIdentityManager.m b/src/Messages/OWSIdentityManager.m index 2856e1039..ceb267895 100644 --- a/src/Messages/OWSIdentityManager.m +++ b/src/Messages/OWSIdentityManager.m @@ -524,6 +524,14 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa OWSAssert(message); OWSAssert(message.recipientIds.count > 0); + if (YES) { + // Don't actually transmit any verification state sync messages + // until we finalize the proto schema changes. + // + // TODO: Remove. + return; + } + [self.messageSender sendMessage:message success:^{ DDLogInfo(@"%@ Successfully sent verification state sync message", self.tag);