Refine UserProfile class. Move local user properties to UserProfile.

// FREEBIE
pull/1/head
Matthew Chen 8 years ago
parent 6bc20ea971
commit 540a0a8e48

@ -17,7 +17,11 @@ class ProfileFetcherJob: NSObject {
static var fetchDateMap = [String: Date]()
public class func run(thread: TSThread, networkManager: TSNetworkManager) {
ProfileFetcherJob(networkManager: networkManager).run(thread: thread)
ProfileFetcherJob(networkManager: networkManager).run(recipientIds: thread.recipientIdentifiers)
}
public class func run(recipientId: String, networkManager: TSNetworkManager) {
ProfileFetcherJob(networkManager: networkManager).run(recipientIds: [recipientId])
}
init(networkManager: TSNetworkManager) {
@ -25,11 +29,11 @@ class ProfileFetcherJob: NSObject {
self.storageManager = TSStorageManager.shared()
}
public func run(thread: TSThread) {
public func run(recipientIds: [String]) {
AssertIsOnMainThread()
DispatchQueue.main.async {
for recipientId in thread.recipientIdentifiers {
for recipientId in recipientIds {
self.updateProfile(recipientId: recipientId)
}
}

@ -75,6 +75,7 @@
#import <SignalServiceKit/OWSDisappearingMessagesConfiguration.h>
#import <SignalServiceKit/OWSIdentityManager.h>
#import <SignalServiceKit/OWSMessageSender.h>
#import <SignalServiceKit/OWSProfilesManager.h>
#import <SignalServiceKit/OWSUnknownContactBlockOfferMessage.h>
#import <SignalServiceKit/OWSVerificationStateChangeMessage.h>
#import <SignalServiceKit/SignalRecipient.h>
@ -966,6 +967,7 @@ typedef enum : NSUInteger {
}
[self updateNavigationBarSubtitleLabel];
[ProfileFetcherJob runWithThread:self.thread networkManager:self.networkManager];
[OWSProfilesManager.sharedManager refreshProfilesForThread:self.thread];
[self markVisibleMessagesAsRead];
}

@ -212,15 +212,14 @@ NS_ASSUME_NONNULL_BEGIN
- (void)updateProfile
{
__weak ProfileViewController *weakSelf = self;
[OWSProfilesManager.sharedManager
updateLocalProfileName:self.nameTextField.text
avatarImage:self.avatar
success:^{
[weakSelf.navigationController popViewControllerAnimated:YES];
}
failure:^{
// <#code#>
}];
[OWSProfilesManager.sharedManager updateLocalProfileName:self.nameTextField.text
avatarImage:self.avatar
success:^{
[weakSelf.navigationController popViewControllerAnimated:YES];
}
failure:^{
// TODO: Handle failure.
}];
}
#pragma mark - UITextFieldDelegate

@ -4,7 +4,6 @@
#import "OWSOutgoingSyncMessage.h"
#import "Cryptography.h"
#import "OWSProfilesManager.h"
#import "OWSSignalServiceProtos.pb.h"
NS_ASSUME_NONNULL_BEGIN

@ -6,7 +6,6 @@ NS_ASSUME_NONNULL_BEGIN
@class ContactsUpdater;
@class OWSBlockingManager;
@class OWSProfilesManager;
@class OWSUploadingService;
@class SignalRecipient;
@class TSInvalidIdentityKeySendingErrorMessage;
@ -59,8 +58,6 @@ NS_SWIFT_NAME(MessageSender)
- (void)setBlockingManager:(OWSBlockingManager *)blockingManager;
- (void)setProfilesManager:(OWSProfilesManager *)profilesManager;
/**
* Send and resend text messages or resend messages with existing attachments.
* If you haven't yet created the attachment, see the `sendAttachmentData:` variants.

@ -14,7 +14,6 @@
#import "OWSMessageServiceParams.h"
#import "OWSOutgoingSentMessageTranscript.h"
#import "OWSOutgoingSyncMessage.h"
#import "OWSProfilesManager.h"
#import "OWSUploadingService.h"
#import "PreKeyBundle+jsonDict.h"
#import "SignalRecipient.h"
@ -356,7 +355,6 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
@property (nonatomic, readonly) TSNetworkManager *networkManager;
@property (nonatomic, readonly) TSStorageManager *storageManager;
@property (nonatomic, readonly) OWSBlockingManager *blockingManager;
@property (nonatomic, readonly) OWSProfilesManager *profilesManager;
@property (nonatomic, readonly) OWSUploadingService *uploadingService;
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
@property (nonatomic, readonly) id<ContactsManagerProtocol> contactsManager;
@ -399,14 +397,6 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
_blockingManager = blockingManager;
}
- (void)setProfilesManager:(OWSProfilesManager *)profilesManager
{
OWSAssert(profilesManager);
OWSAssert(!_profilesManager);
_profilesManager = profilesManager;
}
- (NSOperationQueue *)sendingQueueForMessage:(TSOutgoingMessage *)message
{
OWSAssert(message);

@ -9,7 +9,6 @@
#import "OWSCallHangupMessage.h"
#import "OWSCallIceUpdateMessage.h"
#import "OWSCallOfferMessage.h"
#import "OWSProfilesManager.h"
#import "OWSSignalServiceProtos.pb.h"
#import "TSContactThread.h"

@ -6,7 +6,6 @@
#import "Cryptography.h"
#import "NSDate+millisecondTimeStamp.h"
#import "TSContactThread.h"
#import "OWSProfilesManager.h"
#import "OWSSignalServiceProtos.pb.h"
#import "OWSVerificationStateSyncMessage.h"

@ -499,8 +499,7 @@ NS_ASSUME_NONNULL_BEGIN
if ([content hasProfileKey]) {
NSData *profileKey = [content profileKey];
NSString *recipientId = envelope.source;
[OWSProfilesManager.sharedManager setProfileKey:profileKey
forRecipientId:recipientId];
[OWSProfilesManager setProfileKey:profileKey forRecipientId:recipientId];
}
if (content.hasSyncMessage) {

@ -18,11 +18,10 @@ extern NSString *const kNSNotificationName_OtherUsersProfileDidChange;
#pragma mark - Local Profile
@property (atomic, readonly) NSData *localProfileKey;
// These two methods should only be called from the main thread.
- (NSString *)localProfileName;
- (UIImage *)localProfileAvatarImage;
- (NSData *)localProfileKey;
- (nullable NSString *)localProfileName;
- (nullable UIImage *)localProfileAvatarImage;
// This method is used to update the "local profile" state on the client
// and the service. Client state is only updated if service state is
@ -51,7 +50,7 @@ extern NSString *const kNSNotificationName_OtherUsersProfileDidChange;
#pragma mark - Other User's Profiles
- (void)setProfileKey:(NSData *)profileKey forRecipientId:(NSString *)recipientId;
+ (void)setProfileKey:(NSData *)profileKey forRecipientId:(NSString *)recipientId;
- (nullable NSData *)profileKeyForRecipientId:(NSString *)recipientId;
@ -59,7 +58,7 @@ extern NSString *const kNSNotificationName_OtherUsersProfileDidChange;
- (nullable UIImage *)profileAvatarForRecipientId:(NSString *)recipientId;
- (void)fetchProfileForRecipientId:(NSString *)recipientId;
- (void)refreshProfileForRecipientId:(NSString *)recipientId;
@end

@ -7,7 +7,6 @@
#import "NSDate+OWS.h"
#import "OWSMessageSender.h"
#import "SecurityUtils.h"
#import "TSAccountManager.h"
#import "TSGroupThread.h"
#import "TSStorageManager.h"
#import "TSThread.h"
@ -16,9 +15,14 @@
NS_ASSUME_NONNULL_BEGIN
// UserProfile properties should only be mutated on the main thread.
@interface UserProfile : TSYapDatabaseObject
@property (nonatomic, readonly) NSString *recipientId;
// These properties may be accessed from any thread.
@property (atomic, readonly) NSString *recipientId;
@property (atomic, nullable) NSData *profileKey;
// These properties may be accessed only from the main thread.
@property (nonatomic, nullable) NSString *profileName;
@property (nonatomic, nullable) NSString *avatarUrl;
@property (nonatomic, nullable) NSString *avatarDigest;
@ -28,8 +32,10 @@ NS_ASSUME_NONNULL_BEGIN
// This should reflect when either:
//
// * The last successful update was started.
// * The in-flight update was started.
// * The last successful update finished.
// * The current in-flight update began.
//
// This property may be accessed from any thread.
@property (nonatomic, nullable) NSDate *lastUpdateDate;
- (instancetype)init NS_UNAVAILABLE;
@ -41,10 +47,6 @@ NS_ASSUME_NONNULL_BEGIN
@implementation UserProfile
- (instancetype)initWithRecipientId:(NSString *)recipientId
profileName:(NSString *_Nullable)profileName
avatarUrl:(NSString *_Nullable)avatarUrl
avatarDigest:(NSString *_Nullable)avatarDigest
avatarFileName:(NSString *_Nullable)avatarFileName
{
self = [super initWithUniqueId:recipientId];
@ -54,10 +56,6 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssert(recipientId.length > 0);
_recipientId = recipientId;
_profileName = profileName;
_avatarUrl = avatarUrl;
_avatarDigest = avatarDigest;
_avatarFileName = avatarFileName;
return self;
}
@ -82,19 +80,14 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark -
NSString *const kNSNotificationName_LocalProfileUniqueId = @"kNSNotificationName_LocalProfileUniqueId";
NSString *const kNSNotificationName_LocalProfileDidChange = @"kNSNotificationName_LocalProfileDidChange";
NSString *const kNSNotificationName_OtherUsersProfileDidChange = @"kNSNotificationName_OtherUsersProfileDidChange";
NSString *const kOWSProfilesManager_Collection = @"kOWSProfilesManager_Collection";
// This key is used to persist the local user's profile key.
NSString *const kOWSProfilesManager_LocalProfileSecretKey = @"kOWSProfilesManager_LocalProfileSecretKey";
NSString *const kOWSProfilesManager_UserWhitelistCollection = @"kOWSProfilesManager_UserWhitelistCollection";
NSString *const kOWSProfilesManager_GroupWhitelistCollection = @"kOWSProfilesManager_GroupWhitelistCollection";
NSString *const kOWSProfilesManager_OtherUsersProfileKeysCollection
= @"kOWSProfilesManager_OtherUsersProfileKeysCollection";
// TODO:
static const NSInteger kProfileKeyLength = 16;
@ -103,10 +96,7 @@ static const NSInteger kProfileKeyLength = 16;
@property (nonatomic, readonly) OWSMessageSender *messageSender;
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
// This property should only be mutated on the main thread,
//
// NOTE: Do not access this property directly; use getOrCreateLocalUserProfile instead.
@property (nonatomic, nullable) UserProfile *localUserProfile;
@property (atomic, nullable) UserProfile *localUserProfile;
// This property should only be mutated on the main thread,
@property (nonatomic, nullable) UIImage *localCachedAvatarImage;
@ -115,7 +105,6 @@ static const NSInteger kProfileKeyLength = 16;
// These three properties can be accessed on any thread.
@property (atomic, readonly) NSMutableDictionary<NSString *, NSNumber *> *userProfileWhitelistCache;
@property (atomic, readonly) NSMutableDictionary<NSString *, NSNumber *> *groupProfileWhitelistCache;
@property (atomic, readonly) NSMutableDictionary<NSString *, NSData *> *otherUsersProfileKeyCache;
// This property should only be mutated on the main thread,
@property (nonatomic, readonly) NSCache<NSString *, UIImage *> *otherUsersProfileAvatarImageCache;
@ -161,27 +150,22 @@ static const NSInteger kProfileKeyLength = 16;
_dbConnection = storageManager.newDatabaseConnection;
_userProfileWhitelistCache = [NSMutableDictionary new];
_groupProfileWhitelistCache = [NSMutableDictionary new];
_otherUsersProfileKeyCache = [NSMutableDictionary new];
_otherUsersProfileAvatarImageCache = [NSCache new];
OWSSingletonAssert();
// Register this manager with the message sender.
// This is a circular dependency.
[messageSender setProfilesManager:self];
// Try to load.
_localProfileKey = [self.dbConnection objectForKey:kOWSProfilesManager_LocalProfileSecretKey
inCollection:kOWSProfilesManager_Collection];
if (!_localProfileKey) {
// Generate
_localProfileKey = [OWSProfilesManager generateLocalProfileKey];
// Persist
[self.dbConnection setObject:_localProfileKey
forKey:kOWSProfilesManager_LocalProfileSecretKey
inCollection:kOWSProfilesManager_Collection];
self.localUserProfile = [self getOrCreateUserProfileForRecipientId:kNSNotificationName_LocalProfileUniqueId];
OWSAssert(self.localUserProfile);
if (!self.localUserProfile.profileKey) {
self.localUserProfile.profileKey = [OWSProfilesManager generateLocalProfileKey];
// Make sure to save on the local db connection for consistency.
//
// NOTE: we do an async read/write here to avoid blocking during app launch path.
[self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
[self.localUserProfile saveWithTransaction:transaction];
}];
}
OWSAssert(_localProfileKey.length == kProfileKeyLength);
OWSAssert(self.localUserProfile.profileKey.length == kProfileKeyLength);
return self;
}
@ -206,44 +190,36 @@ static const NSInteger kProfileKeyLength = 16;
#pragma mark - User Profile Accessor
// This method can be safely called from any thread.
- (UserProfile *)getOrCreateUserProfileForRecipientId:(NSString *)recipientId
{
OWSAssert([NSThread isMainThread]);
OWSAssert(recipientId.length > 0);
__block UserProfile *instance;
// Make sure to read on the local db connection for consistency.
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
instance = [UserProfile fetchObjectWithUniqueID:recipientId transaction:transaction];
if (!instance) {
instance = [[UserProfile alloc] initWithRecipientId:recipientId
profileName:nil
avatarUrl:nil
avatarDigest:nil
avatarFileName:nil];
[instance saveWithTransaction:transaction];
}
}];
if (!instance) {
instance = [[UserProfile alloc] initWithRecipientId:recipientId];
}
OWSAssert(instance);
return instance;
}
- (nullable UserProfile *)getOrCreateLocalUserProfile
// All writes to user profiles should occur on the main thread.
- (void)saveUserProfile:(UserProfile *)userProfile
{
OWSAssert([NSThread isMainThread]);
OWSAssert(userProfile);
if (!self.localUserProfile) {
NSString *_Nullable recipientId = [TSAccountManager localNumber];
if (!recipientId) {
OWSFail(@"Missing local number.");
return nil;
}
self.localUserProfile = [self getOrCreateUserProfileForRecipientId:recipientId];
}
return self.localUserProfile;
// Make sure to save on the local db connection for consistency.
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[userProfile saveWithTransaction:transaction];
}];
}
#pragma mark - Local Profile Key
@ -257,14 +233,21 @@ static const NSInteger kProfileKeyLength = 16;
#pragma mark - Local Profile
- (NSString *)localProfileName
- (NSData *)localProfileKey
{
OWSAssert(self.localUserProfile.profileKey.length == kProfileKeyLength);
return self.localUserProfile.profileKey;
}
- (nullable NSString *)localProfileName
{
OWSAssert([NSThread isMainThread]);
return [self getOrCreateLocalUserProfile].profileName;
return self.localUserProfile.profileName;
}
- (UIImage *)localProfileAvatarImage
- (nullable UIImage *)localProfileAvatarImage
{
OWSAssert([NSThread isMainThread]);
@ -299,16 +282,15 @@ static const NSInteger kProfileKeyLength = 16;
success:^{
// All reads and writes to user profiles should happen on the main thread.
dispatch_async(dispatch_get_main_queue(), ^{
UserProfile *userProfile = [self getOrCreateLocalUserProfile];
UserProfile *userProfile = self.localUserProfile;
OWSAssert(userProfile);
userProfile.profileName = profileName;
userProfile.avatarUrl = avatarUrl;
userProfile.avatarDigest = avatarDigest;
userProfile.avatarFileName = avatarFileName;
// Make sure to save on the local db connection for consistency.
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[userProfile saveWithTransaction:transaction];
}];
[self saveUserProfile:userProfile];
self.localCachedAvatarImage = avatarImage;
successBlock();
@ -323,7 +305,7 @@ static const NSInteger kProfileKeyLength = 16;
}];
};
UserProfile *userProfile = [self getOrCreateLocalUserProfile];
UserProfile *userProfile = self.localUserProfile;
OWSAssert(userProfile);
// If we have a new avatar image, we must first:
@ -536,43 +518,41 @@ static const NSInteger kProfileKeyLength = 16;
#pragma mark - Other User's Profiles
+ (void)setProfileKey:(NSData *)profileKey forRecipientId:(NSString *)recipientId
{
dispatch_async(dispatch_get_main_queue(), ^{
[[self sharedManager] setProfileKey:profileKey forRecipientId:recipientId];
});
}
- (void)setProfileKey:(NSData *)profileKey forRecipientId:(NSString *)recipientId
{
OWSAssert([NSThread isMainThread]);
OWSAssert(profileKey.length == kProfileKeyLength);
OWSAssert(recipientId.length > 0);
if (profileKey.length != kProfileKeyLength) {
return;
}
NSData *_Nullable existingProfileKey = [self profileKeyForRecipientId:recipientId];
if (existingProfileKey &&
[existingProfileKey isEqual:profileKey]) {
UserProfile *userProfile = [self getOrCreateUserProfileForRecipientId:recipientId];
OWSAssert(userProfile);
if (userProfile.profileKey && [userProfile.profileKey isEqual:profileKey]) {
// Ignore redundant update.
return;
}
[self.dbConnection setObject:profileKey
forKey:recipientId
inCollection:kOWSProfilesManager_OtherUsersProfileKeysCollection];
self.otherUsersProfileKeyCache[recipientId] = profileKey;
userProfile.profileKey = profileKey;
[self saveUserProfile:userProfile];
}
- (nullable NSData *)profileKeyForRecipientId:(NSString *)recipientId
{
OWSAssert(recipientId.length > 0);
NSData *_Nullable profileKey = self.otherUsersProfileKeyCache[recipientId];
if (profileKey.length > 0) {
return profileKey;
}
profileKey =
[self.dbConnection dataForKey:recipientId inCollection:kOWSProfilesManager_OtherUsersProfileKeysCollection];
if (profileKey) {
OWSAssert(profileKey.length == kProfileKeyLength);
self.otherUsersProfileKeyCache[recipientId] = profileKey;
}
return profileKey;
UserProfile *userProfile = [self getOrCreateUserProfileForRecipientId:recipientId];
OWSAssert(userProfile);
return userProfile.profileKey;
}
- (nullable NSString *)profileNameForRecipientId:(NSString *)recipientId
@ -580,7 +560,7 @@ static const NSInteger kProfileKeyLength = 16;
OWSAssert([NSThread isMainThread]);
OWSAssert(recipientId.length > 0);
[self fetchProfileForRecipientId:recipientId];
[self refreshProfileForRecipientId:recipientId];
UserProfile *userProfile = [self getOrCreateUserProfileForRecipientId:recipientId];
return userProfile.profileName;
@ -591,7 +571,7 @@ static const NSInteger kProfileKeyLength = 16;
OWSAssert([NSThread isMainThread]);
OWSAssert(recipientId.length > 0);
[self fetchProfileForRecipientId:recipientId];
[self refreshProfileForRecipientId:recipientId];
UIImage *_Nullable image = [self.otherUsersProfileAvatarImageCache objectForKey:recipientId];
if (image) {
@ -609,8 +589,9 @@ static const NSInteger kProfileKeyLength = 16;
return image;
}
- (void)fetchProfileForRecipientId:(NSString *)recipientId
- (void)refreshProfileForRecipientId:(NSString *)recipientId
{
OWSAssert([NSThread isMainThread]);
OWSAssert(recipientId.length > 0);
UserProfile *userProfile = [self getOrCreateUserProfileForRecipientId:recipientId];
@ -623,9 +604,8 @@ static const NSInteger kProfileKeyLength = 16;
}
userProfile.lastUpdateDate = [NSDate new];
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[userProfile saveWithTransaction:transaction];
}];
[self saveUserProfile:userProfile];
// TODO: Actually update the profile.
}

Loading…
Cancel
Save