Add profile key to proto schema. Send and receive profile keys. Cache profile manager state.

// FREEBIE
pull/1/head
Matthew Chen 7 years ago
parent e58358ce53
commit 26b668cce7

@ -9,6 +9,7 @@
#import "ViewControllerUtils.h"
#import <SignalServiceKit/ContactsUpdater.h>
#import <SignalServiceKit/OWSError.h>
#import <SignalServiceKit/OWSProfilesManager.h>
#import <SignalServiceKit/SignalAccount.h>
#import <SignalServiceKit/TSStorageManager.h>
@ -205,6 +206,8 @@ NSString *const kTSStorageManager_AccountLastNames = @"kTSStorageManager_Account
self.signalAccountMap = [signalAccountMap copy];
self.signalAccounts = [signalAccounts copy];
[OWSProfilesManager.sharedManager setContactRecipientIds:signalAccountMap.allKeys];
[self updateCachedDisplayNames];
});
});

@ -35,7 +35,7 @@ message Content {
optional SyncMessage syncMessage = 2;
optional CallMessage callMessage = 3;
optional NullMessage nullMessage = 4;
optional string profileKey = 5;
optional bytes profileKey = 5;
}
message NullMessage {

@ -3,8 +3,9 @@
//
#import "OWSOutgoingSyncMessage.h"
#import "OWSSignalServiceProtos.pb.h"
#import "Cryptography.h"
#import "OWSProfilesManager.h"
#import "OWSSignalServiceProtos.pb.h"
NS_ASSUME_NONNULL_BEGIN
@ -44,6 +45,12 @@ NS_ASSUME_NONNULL_BEGIN
{
OWSSignalServiceProtosContentBuilder *contentBuilder = [OWSSignalServiceProtosContentBuilder new];
[contentBuilder setSyncMessage:[self buildSyncMessage]];
#ifndef SKIP_PROFILE_KEYS
if (OWSProfilesManager.sharedManager.localProfileKey) {
[contentBuilder setProfileKey:OWSProfilesManager.sharedManager.localProfileKey];
}
#endif
return [[contentBuilder build] data];
}

@ -4,6 +4,7 @@
#import "TSOutgoingMessage.h"
#import "NSDate+millisecondTimeStamp.h"
#import "OWSProfilesManager.h"
#import "OWSSignalServiceProtos.pb.h"
#import "TSAttachmentStream.h"
#import "TSContactThread.h"
@ -459,6 +460,19 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
{
OWSSignalServiceProtosContentBuilder *contentBuilder = [OWSSignalServiceProtosContentBuilder new];
contentBuilder.dataMessage = [self buildDataMessage];
#ifndef SKIP_PROFILE_KEYS
OWSAssert([self.thread isKindOfClass:[TSContactThread class]]);
if ([self.thread isKindOfClass:[TSContactThread class]]) {
TSContactThread *contactThread = (TSContactThread *)self.thread;
NSString *recipientId = contactThread.contactIdentifier;
if (OWSProfilesManager.sharedManager.localProfileKey &&
[OWSProfilesManager.sharedManager isUserInProfileWhitelist:recipientId]) {
[contentBuilder setProfileKey:OWSProfilesManager.sharedManager.localProfileKey];
}
}
#endif
return [[contentBuilder build] data];
}

@ -9,7 +9,9 @@
#import "OWSCallHangupMessage.h"
#import "OWSCallIceUpdateMessage.h"
#import "OWSCallOfferMessage.h"
#import "OWSProfilesManager.h"
#import "OWSSignalServiceProtos.pb.h"
#import "TSContactThread.h"
NS_ASSUME_NONNULL_BEGIN
@ -124,6 +126,19 @@ NS_ASSUME_NONNULL_BEGIN
{
OWSSignalServiceProtosContentBuilder *contentBuilder = [OWSSignalServiceProtosContentBuilder new];
[contentBuilder setCallMessage:[self asProtobuf]];
#ifndef SKIP_PROFILE_KEYS
OWSAssert([self.thread isKindOfClass:[TSContactThread class]]);
if ([self.thread isKindOfClass:[TSContactThread class]]) {
TSContactThread *contactThread = (TSContactThread *)self.thread;
NSString *recipientId = contactThread.contactIdentifier;
if (OWSProfilesManager.sharedManager.localProfileKey &&
[OWSProfilesManager.sharedManager isUserInProfileWhitelist:recipientId]) {
[contentBuilder setProfileKey:OWSProfilesManager.sharedManager.localProfileKey];
}
}
#endif
return [[contentBuilder build] data];
}

@ -3,11 +3,12 @@
//
#import "OWSOutgoingNullMessage.h"
#import "OWSSignalServiceProtos.pb.h"
#import "Cryptography.h"
#import "OWSVerificationStateSyncMessage.h"
#import "NSDate+millisecondTimeStamp.h"
#import "TSContactThread.h"
#import "OWSProfilesManager.h"
#import "OWSSignalServiceProtos.pb.h"
#import "OWSVerificationStateSyncMessage.h"
NS_ASSUME_NONNULL_BEGIN
@ -57,6 +58,19 @@ NS_ASSUME_NONNULL_BEGIN
contentBuilder.nullMessage = [nullMessageBuilder build];
#ifndef SKIP_PROFILE_KEYS
OWSAssert([self.thread isKindOfClass:[TSContactThread class]]);
if ([self.thread isKindOfClass:[TSContactThread class]]) {
TSContactThread *contactThread = (TSContactThread *)self.thread;
NSString *recipientId = contactThread.contactIdentifier;
if (OWSProfilesManager.sharedManager.localProfileKey &&
[OWSProfilesManager.sharedManager isUserInProfileWhitelist:recipientId]) {
[contentBuilder setProfileKey:OWSProfilesManager.sharedManager.localProfileKey];
}
}
#endif
return [contentBuilder build].data;
}

@ -278,16 +278,16 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
#define Content_profileKey @"profileKey"
@interface OWSSignalServiceProtosContent : PBGeneratedMessage<GeneratedMessageProtocol> {
@private
BOOL hasProfileKey_:1;
BOOL hasDataMessage_:1;
BOOL hasSyncMessage_:1;
BOOL hasCallMessage_:1;
BOOL hasNullMessage_:1;
NSString* profileKey;
BOOL hasProfileKey_:1;
OWSSignalServiceProtosDataMessage* dataMessage;
OWSSignalServiceProtosSyncMessage* syncMessage;
OWSSignalServiceProtosCallMessage* callMessage;
OWSSignalServiceProtosNullMessage* nullMessage;
NSData* profileKey;
}
- (BOOL) hasDataMessage;
- (BOOL) hasSyncMessage;
@ -298,7 +298,7 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
@property (readonly, strong) OWSSignalServiceProtosSyncMessage* syncMessage;
@property (readonly, strong) OWSSignalServiceProtosCallMessage* callMessage;
@property (readonly, strong) OWSSignalServiceProtosNullMessage* nullMessage;
@property (readonly, strong) NSString* profileKey;
@property (readonly, strong) NSData* profileKey;
+ (instancetype) defaultInstance;
- (instancetype) defaultInstance;
@ -364,8 +364,8 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
- (OWSSignalServiceProtosContentBuilder*) clearNullMessage;
- (BOOL) hasProfileKey;
- (NSString*) profileKey;
- (OWSSignalServiceProtosContentBuilder*) setProfileKey:(NSString*) value;
- (NSData*) profileKey;
- (OWSSignalServiceProtosContentBuilder*) setProfileKey:(NSData*) value;
- (OWSSignalServiceProtosContentBuilder*) clearProfileKey;
@end

@ -560,7 +560,7 @@ NSString *NSStringFromOWSSignalServiceProtosEnvelopeType(OWSSignalServiceProtosE
@property (strong) OWSSignalServiceProtosSyncMessage* syncMessage;
@property (strong) OWSSignalServiceProtosCallMessage* callMessage;
@property (strong) OWSSignalServiceProtosNullMessage* nullMessage;
@property (strong) NSString* profileKey;
@property (strong) NSData* profileKey;
@end
@implementation OWSSignalServiceProtosContent
@ -606,7 +606,7 @@ NSString *NSStringFromOWSSignalServiceProtosEnvelopeType(OWSSignalServiceProtosE
self.syncMessage = [OWSSignalServiceProtosSyncMessage defaultInstance];
self.callMessage = [OWSSignalServiceProtosCallMessage defaultInstance];
self.nullMessage = [OWSSignalServiceProtosNullMessage defaultInstance];
self.profileKey = @"";
self.profileKey = [NSData data];
}
return self;
}
@ -639,7 +639,7 @@ static OWSSignalServiceProtosContent* defaultOWSSignalServiceProtosContentInstan
[output writeMessage:4 value:self.nullMessage];
}
if (self.hasProfileKey) {
[output writeString:5 value:self.profileKey];
[output writeData:5 value:self.profileKey];
}
[self.unknownFields writeToCodedOutputStream:output];
}
@ -663,7 +663,7 @@ static OWSSignalServiceProtosContent* defaultOWSSignalServiceProtosContentInstan
size_ += computeMessageSize(4, self.nullMessage);
}
if (self.hasProfileKey) {
size_ += computeStringSize(5, self.profileKey);
size_ += computeDataSize(5, self.profileKey);
}
size_ += self.unknownFields.serializedSize;
memoizedSerializedSize = size_;
@ -909,7 +909,7 @@ static OWSSignalServiceProtosContent* defaultOWSSignalServiceProtosContentInstan
break;
}
case 42: {
[self setProfileKey:[input readString]];
[self setProfileKey:[input readData]];
break;
}
}
@ -1038,17 +1038,17 @@ static OWSSignalServiceProtosContent* defaultOWSSignalServiceProtosContentInstan
- (BOOL) hasProfileKey {
return resultContent.hasProfileKey;
}
- (NSString*) profileKey {
- (NSData*) profileKey {
return resultContent.profileKey;
}
- (OWSSignalServiceProtosContentBuilder*) setProfileKey:(NSString*) value {
- (OWSSignalServiceProtosContentBuilder*) setProfileKey:(NSData*) value {
resultContent.hasProfileKey = YES;
resultContent.profileKey = value;
return self;
}
- (OWSSignalServiceProtosContentBuilder*) clearProfileKey {
resultContent.hasProfileKey = NO;
resultContent.profileKey = @"";
resultContent.profileKey = [NSData data];
return self;
}
@end

@ -19,6 +19,7 @@
#import "OWSIncomingMessageFinder.h"
#import "OWSIncomingSentMessageTranscript.h"
#import "OWSMessageSender.h"
#import "OWSProfilesManager.h"
#import "OWSReadReceiptsProcessor.h"
#import "OWSRecordTranscriptJob.h"
#import "OWSSyncContactsMessage.h"
@ -494,6 +495,16 @@ NS_ASSUME_NONNULL_BEGIN
if (envelope.hasContent) {
OWSSignalServiceProtosContent *content = [OWSSignalServiceProtosContent parseFromData:plaintextData];
DDLogInfo(@"%@ handling content: <Content: %@>", self.tag, [self descriptionForContent:content]);
#ifndef SKIP_PROFILE_KEYS
if ([content hasProfileKey]) {
NSData *profileKey = [content profileKey];
NSString *recipientId = envelope.source;
[OWSProfilesManager.sharedManager setProfileKey:profileKey
forRecipientId:recipientId];
}
#endif
if (content.hasSyncMessage) {
[self handleIncomingEnvelope:envelope withSyncMessage:content.syncMessage];
} else if (content.hasDataMessage) {

@ -6,6 +6,9 @@ NS_ASSUME_NONNULL_BEGIN
extern NSString *const kNSNotificationName_LocalProfileDidChange;
// TODO: Remove feature flag
//#define SKIP_PROFILE_KEYS
// This class can be safely accessed and used from any thread.
@interface OWSProfilesManager : NSObject
@ -15,6 +18,7 @@ extern NSString *const kNSNotificationName_LocalProfileDidChange;
#pragma mark - Local Profile
@property (atomic, readonly) NSData *localProfileKey;
@property (atomic, nullable, readonly) NSString *localProfileName;
@property (atomic, nullable, readonly) UIImage *localProfileAvatarImage;
@ -34,6 +38,8 @@ extern NSString *const kNSNotificationName_LocalProfileDidChange;
- (BOOL)isUserInProfileWhitelist:(NSString *)recipientId;
- (void)setContactRecipientIds:(NSArray<NSString *> *)contactRecipientIds;
#pragma mark - Known Profile Keys
- (void)setProfileKey:(NSData *)profileKey forRecipientId:(NSString *)recipientId;

@ -94,22 +94,22 @@ static const NSInteger kProfileKeyLength = 16;
@property (nonatomic, readonly) OWSMessageSender *messageSender;
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
@property (atomic, readonly, nullable) NSData *localProfileKey;
// These properties should only be mutated on the main thread,
// but they may be accessed on other threads.
@property (atomic, nullable) NSString *localProfileName;
@property (atomic, nullable) UIImage *localProfileAvatarImage;
@property (atomic, nullable) AvatarMetadata *localProfileAvatarMetadata;
// These caches are lazy-populated. The single point truth is the database.
@property (nonatomic, readonly) NSMutableDictionary<NSString *, NSNumber *>*profileWhitelistCache;
@property (nonatomic, readonly) NSMutableDictionary<NSString *, NSData *>*knownProfileKeyCache;
@end
#pragma mark -
@implementation OWSProfilesManager
@synthesize localProfileKey = _localProfileKey;
+ (instancetype)sharedManager
{
static OWSProfilesManager *sharedMyManager = nil;
@ -137,11 +137,14 @@ static const NSInteger kProfileKeyLength = 16;
return self;
}
OWSAssert([NSThread isMainThread]);
OWSAssert(storageManager);
OWSAssert(messageSender);
_messageSender = messageSender;
_dbConnection = storageManager.newDatabaseConnection;
_profileWhitelistCache = [NSMutableDictionary new];
_knownProfileKeyCache = [NSMutableDictionary new];
OWSSingletonAssert();
@ -414,13 +417,35 @@ static const NSInteger kProfileKeyLength = 16;
OWSAssert(recipientId.length > 0);
[self.dbConnection setObject:@(1) forKey:recipientId inCollection:kOWSProfilesManager_WhitelistCollection];
self.profileWhitelistCache[recipientId] = @(YES);
}
- (BOOL)isUserInProfileWhitelist:(NSString *)recipientId
{
OWSAssert(recipientId.length > 0);
return (nil != [self.dbConnection objectForKey:recipientId inCollection:kOWSProfilesManager_WhitelistCollection]);
NSNumber *_Nullable value = self.profileWhitelistCache[recipientId];
if (value) {
return [value boolValue];
}
value = @(nil != [self.dbConnection objectForKey:recipientId inCollection:kOWSProfilesManager_WhitelistCollection]);
self.profileWhitelistCache[recipientId] = value;
return [value boolValue];
}
- (void)setContactRecipientIds:(NSArray<NSString *> *)contactRecipientIds
{
OWSAssert(contactRecipientIds);
// TODO: The persisted whitelist could either be:
//
// * Just users manually added to the whitelist.
// * Also include users auto-added by, for example, being in the user's
// contacts or when the user initiates a 1:1 conversation with them, etc.
for (NSString *recipientId in contactRecipientIds) {
[self addUserToProfileWhitelist:recipientId];
}
}
#pragma mark - Known Profile Keys
@ -429,20 +454,37 @@ static const NSInteger kProfileKeyLength = 16;
{
OWSAssert(profileKey.length == kProfileKeyLength);
OWSAssert(recipientId.length > 0);
if (profileKey.length != kProfileKeyLength) {
return;
}
NSData *_Nullable existingProfileKey = [self profileKeyForRecipientId:recipientId];
if (existingProfileKey &&
[existingProfileKey isEqual:profileKey]) {
// Ignore redundant update.
return;
}
[self.dbConnection setObject:profileKey
forKey:recipientId
inCollection:kOWSProfilesManager_KnownProfileKeysCollection];
self.knownProfileKeyCache[recipientId] = profileKey;
}
- (nullable NSData *)profileKeyForRecipientId:(NSString *)recipientId
{
OWSAssert(recipientId.length > 0);
NSData *_Nullable profileKey =
[self.dbConnection objectForKey:recipientId inCollection:kOWSProfilesManager_KnownProfileKeysCollection];
NSData *_Nullable profileKey = self.knownProfileKeyCache[recipientId];
if (profileKey.length > 0) {
return profileKey;
}
profileKey =
[self.dbConnection objectForKey:recipientId inCollection:kOWSProfilesManager_KnownProfileKeysCollection];
if (profileKey) {
OWSAssert(profileKey.length == kProfileKeyLength);
self.knownProfileKeyCache[recipientId] = profileKey;
}
return profileKey;
}

Loading…
Cancel
Save