Rework thread safety in profile manager.

pull/1/head
Matthew Chen 7 years ago
parent c1d435c9d8
commit 911c4d380b

@ -107,6 +107,8 @@
3478506A1FD9B78A007B8332 /* AppSetup.h in Headers */ = {isa = PBXBuildFile; fileRef = 347850661FD9B789007B8332 /* AppSetup.h */; settings = {ATTRIBUTES = (Public, ); }; };
3478506B1FD9B78A007B8332 /* NoopCallMessageHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 347850671FD9B78A007B8332 /* NoopCallMessageHandler.swift */; };
3478506C1FD9B78A007B8332 /* NoopNotificationsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 347850681FD9B78A007B8332 /* NoopNotificationsManager.swift */; };
347850711FDAEB17007B8332 /* OWSUserProfile.m in Sources */ = {isa = PBXBuildFile; fileRef = 3478506F1FDAEB16007B8332 /* OWSUserProfile.m */; };
347850721FDAEB17007B8332 /* OWSUserProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 347850701FDAEB16007B8332 /* OWSUserProfile.h */; };
3497DBEC1ECE257500DB2605 /* OWSCountryMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 3497DBEB1ECE257500DB2605 /* OWSCountryMetadata.m */; };
3497DBEF1ECE2E4700DB2605 /* DomainFrontingCountryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3497DBEE1ECE2E4700DB2605 /* DomainFrontingCountryViewController.m */; };
34B0796D1FCF46B100E248C2 /* MainAppContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B0796B1FCF46B000E248C2 /* MainAppContext.m */; };
@ -584,6 +586,8 @@
347850661FD9B789007B8332 /* AppSetup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppSetup.h; sourceTree = "<group>"; };
347850671FD9B78A007B8332 /* NoopCallMessageHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NoopCallMessageHandler.swift; sourceTree = "<group>"; };
347850681FD9B78A007B8332 /* NoopNotificationsManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NoopNotificationsManager.swift; sourceTree = "<group>"; };
3478506F1FDAEB16007B8332 /* OWSUserProfile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSUserProfile.m; sourceTree = "<group>"; };
347850701FDAEB16007B8332 /* OWSUserProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSUserProfile.h; sourceTree = "<group>"; };
348F2EAD1F0D21BC00D4ECE0 /* DeviceSleepManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceSleepManager.swift; sourceTree = "<group>"; };
3495BC911F1426B800B478F5 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = translations/ar.lproj/Localizable.strings; sourceTree = "<group>"; };
3497DBEA1ECE257500DB2605 /* OWSCountryMetadata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSCountryMetadata.h; sourceTree = "<group>"; };
@ -1225,6 +1229,8 @@
children = (
346129B11FD1F7E800532771 /* OWSProfileManager.h */,
346129B21FD1F7E800532771 /* OWSProfileManager.m */,
347850701FDAEB16007B8332 /* OWSUserProfile.h */,
3478506F1FDAEB16007B8332 /* OWSUserProfile.m */,
346129B31FD1F7E800532771 /* ProfileFetcherJob.swift */,
);
path = profiles;
@ -2041,6 +2047,7 @@
3461295A1FD1D74C00532771 /* Environment.h in Headers */,
34480B631FD0A98800BC14EF /* UIView+OWS.h in Headers */,
451F8A4B1FD715E1005CB9DA /* OWSGroupAvatarBuilder.h in Headers */,
347850721FDAEB17007B8332 /* OWSUserProfile.h in Headers */,
451F8A371FD71179005CB9DA /* OWSViewController.h in Headers */,
454A965D1FD602B1008D2A0E /* OWSAudioAttachmentPlayer.h in Headers */,
451F8A3E1FD713D2005CB9DA /* ThreadViewHelper.h in Headers */,
@ -2730,6 +2737,7 @@
346129F71FD5F31400532771 /* OWS105AttachmentFilePaths.m in Sources */,
45194F931FD7215C00333B2C /* OWSContactOffersInteraction.m in Sources */,
450998681FD8C0FF00D89EB3 /* AttachmentSharing.m in Sources */,
347850711FDAEB17007B8332 /* OWSUserProfile.m in Sources */,
346129761FD1E0B500532771 /* WeakTimer.swift in Sources */,
346129F81FD5F31400532771 /* OWS100RemoveTSRecipientsMigration.m in Sources */,
45E547201FD755E700DFC09E /* AttachmentApprovalViewController.swift in Sources */,

@ -356,7 +356,6 @@ static NSString *const kURLHostVerifyPrefix = @"verify";
return NO;
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
DDLogWarn(@"%@ applicationDidBecomeActive.", self.logTag);

File diff suppressed because it is too large Load Diff

@ -0,0 +1,83 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import <SignalServiceKit/TSYapDatabaseObject.h>
NS_ASSUME_NONNULL_BEGIN
typedef void (^OWSUserProfileCompletion)(void);
@class OWSAES256Key;
extern NSString *const kLocalProfileUniqueId;
// This class should be completely thread-safe.
@interface OWSUserProfile : TSYapDatabaseObject
@property (atomic, readonly) NSString *recipientId;
@property (atomic, readonly, nullable) OWSAES256Key *profileKey;
@property (atomic, readonly, nullable) NSString *profileName;
@property (atomic, readonly, nullable) NSString *avatarUrlPath;
// This filename is relative to OWSProfileManager.profileAvatarsDirPath.
@property (atomic, readonly, nullable) NSString *avatarFileName;
// This should reflect when either:
//
// * The last successful update finished.
// * The current in-flight update began.
@property (atomic, readonly, nullable) NSDate *lastUpdateDate;
- (instancetype)init NS_UNAVAILABLE;
+ (OWSUserProfile *)getOrBuildUserProfileForRecipientId:(NSString *)recipientId
dbConnection:(YapDatabaseConnection *)dbConnection;
#pragma mark - Update With... Methods
- (void)updateWithProfileName:(nullable NSString *)profileName
profileKey:(OWSAES256Key *)profileKey
avatarUrlPath:(nullable NSString *)avatarUrlPath
avatarFileName:(nullable NSString *)avatarFileName
dbConnection:(YapDatabaseConnection *)dbConnection
completion:(nullable OWSUserProfileCompletion)completion;
- (void)updateWithProfileName:(nullable NSString *)profileName
avatarUrlPath:(nullable NSString *)avatarUrlPath
avatarFileName:(nullable NSString *)avatarFileName
dbConnection:(YapDatabaseConnection *)dbConnection
completion:(nullable OWSUserProfileCompletion)completion;
- (void)updateWithProfileName:(nullable NSString *)profileName
avatarUrlPath:(nullable NSString *)avatarUrlPath
avatarFileName:(nullable NSString *)avatarFileName
lastUpdateDate:(nullable NSDate *)lastUpdateDate
dbConnection:(YapDatabaseConnection *)dbConnection
completion:(nullable OWSUserProfileCompletion)completion;
- (void)updateWithProfileName:(nullable NSString *)profileName
avatarUrlPath:(nullable NSString *)avatarUrlPath
lastUpdateDate:(nullable NSDate *)lastUpdateDate
dbConnection:(YapDatabaseConnection *)dbConnection
completion:(nullable OWSUserProfileCompletion)completion;
- (void)updateWithAvatarUrlPath:(nullable NSString *)avatarUrlPath
avatarFileName:(nullable NSString *)avatarFileName
dbConnection:(YapDatabaseConnection *)dbConnection
completion:(nullable OWSUserProfileCompletion)completion;
- (void)updateWithAvatarFileName:(nullable NSString *)avatarFileName
dbConnection:(YapDatabaseConnection *)dbConnection
completion:(nullable OWSUserProfileCompletion)completion;
- (void)updateWithLastUpdateDate:(nullable NSDate *)lastUpdateDate
dbConnection:(YapDatabaseConnection *)dbConnection
completion:(nullable OWSUserProfileCompletion)completion;
- (void)clearWithProfileKey:(OWSAES256Key *)profileKey
dbConnection:(YapDatabaseConnection *)dbConnection
completion:(nullable OWSUserProfileCompletion)completion;
@end
NS_ASSUME_NONNULL_END

@ -0,0 +1,250 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "OWSUserProfile.h"
#import "NSString+OWS.h"
#import <SignalServiceKit/Cryptography.h>
#import <YapDatabase/YapDatabaseConnection.h>
NS_ASSUME_NONNULL_BEGIN
NSString *const kLocalProfileUniqueId = @"kLocalProfileUniqueId";
@interface OWSUserProfile ()
@property (atomic, nullable) OWSAES256Key *profileKey;
@property (atomic, nullable) NSString *profileName;
@property (atomic, nullable) NSString *avatarUrlPath;
@property (atomic, nullable) NSString *avatarFileName;
@property (atomic, nullable) NSDate *lastUpdateDate;
@end
#pragma mark -
@implementation OWSUserProfile
+ (OWSUserProfile *)getOrBuildUserProfileForRecipientId:(NSString *)recipientId
dbConnection:(YapDatabaseConnection *)dbConnection
{
OWSAssert(recipientId.length > 0);
__block OWSUserProfile *userProfile;
[dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
userProfile = [OWSUserProfile fetchObjectWithUniqueID:recipientId transaction:transaction];
}];
if (!userProfile) {
userProfile = [[OWSUserProfile alloc] initWithRecipientId:recipientId];
if ([recipientId isEqualToString:kLocalProfileUniqueId]) {
[userProfile updateImmediatelyWithProfileKey:[OWSAES256Key generateRandomKey]
dbConnection:dbConnection
completion:nil];
}
}
OWSAssert(userProfile);
return userProfile;
}
- (instancetype)initWithRecipientId:(NSString *)recipientId
{
self = [super initWithUniqueId:recipientId];
if (!self) {
return self;
}
OWSAssert(recipientId.length > 0);
_recipientId = recipientId;
return self;
}
#pragma mark - Update With... Methods
- (void)updateWithProfileName:(nullable NSString *)profileName
avatarUrlPath:(nullable NSString *)avatarUrlPath
avatarFileName:(nullable NSString *)avatarFileName
dbConnection:(YapDatabaseConnection *)dbConnection
completion:(nullable OWSUserProfileCompletion)completion
{
[dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self applyChangeToSelfAndLatestCopy:transaction
changeBlock:^(OWSUserProfile *userProfile) {
[userProfile setProfileName:[profileName ows_stripped]];
[userProfile setAvatarUrlPath:avatarUrlPath];
[userProfile setAvatarFileName:avatarFileName];
}];
}
completionBlock:completion];
}
- (void)updateWithProfileName:(nullable NSString *)profileName
avatarUrlPath:(nullable NSString *)avatarUrlPath
avatarFileName:(nullable NSString *)avatarFileName
lastUpdateDate:(nullable NSDate *)lastUpdateDate
dbConnection:(YapDatabaseConnection *)dbConnection
completion:(nullable OWSUserProfileCompletion)completion
{
[dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self applyChangeToSelfAndLatestCopy:transaction
changeBlock:^(OWSUserProfile *userProfile) {
[userProfile setProfileName:[profileName ows_stripped]];
[userProfile setAvatarUrlPath:avatarUrlPath];
[userProfile setAvatarFileName:avatarFileName];
[userProfile setLastUpdateDate:lastUpdateDate];
}];
}
completionBlock:completion];
}
- (void)updateWithProfileName:(nullable NSString *)profileName
avatarUrlPath:(nullable NSString *)avatarUrlPath
lastUpdateDate:(nullable NSDate *)lastUpdateDate
dbConnection:(YapDatabaseConnection *)dbConnection
completion:(nullable OWSUserProfileCompletion)completion
{
[dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self applyChangeToSelfAndLatestCopy:transaction
changeBlock:^(OWSUserProfile *userProfile) {
[userProfile setProfileName:[profileName ows_stripped]];
[userProfile setAvatarUrlPath:avatarUrlPath];
[userProfile setLastUpdateDate:lastUpdateDate];
}];
}
completionBlock:completion];
}
- (void)updateWithProfileName:(nullable NSString *)profileName
profileKey:(OWSAES256Key *)profileKey
avatarUrlPath:(nullable NSString *)avatarUrlPath
avatarFileName:(nullable NSString *)avatarFileName
dbConnection:(YapDatabaseConnection *)dbConnection
completion:(nullable OWSUserProfileCompletion)completion
{
[dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self applyChangeToSelfAndLatestCopy:transaction
changeBlock:^(OWSUserProfile *userProfile) {
[userProfile setProfileName:[profileName ows_stripped]];
[userProfile setProfileKey:profileKey];
[userProfile setAvatarUrlPath:avatarUrlPath];
[userProfile setAvatarFileName:avatarFileName];
}];
}
completionBlock:completion];
}
- (void)updateWithAvatarUrlPath:(nullable NSString *)avatarUrlPath
avatarFileName:(nullable NSString *)avatarFileName
dbConnection:(YapDatabaseConnection *)dbConnection
completion:(nullable OWSUserProfileCompletion)completion
{
[dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self applyChangeToSelfAndLatestCopy:transaction
changeBlock:^(OWSUserProfile *userProfile) {
[userProfile setAvatarUrlPath:avatarUrlPath];
[userProfile setAvatarFileName:avatarFileName];
}];
}
completionBlock:completion];
}
- (void)updateWithAvatarFileName:(nullable NSString *)avatarFileName
dbConnection:(YapDatabaseConnection *)dbConnection
completion:(nullable OWSUserProfileCompletion)completion
{
[dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self applyChangeToSelfAndLatestCopy:transaction
changeBlock:^(OWSUserProfile *userProfile) {
[userProfile setAvatarFileName:avatarFileName];
}];
}
completionBlock:completion];
}
- (void)updateWithLastUpdateDate:(nullable NSDate *)lastUpdateDate
dbConnection:(YapDatabaseConnection *)dbConnection
completion:(nullable OWSUserProfileCompletion)completion
{
[dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self applyChangeToSelfAndLatestCopy:transaction
changeBlock:^(OWSUserProfile *userProfile) {
[userProfile setLastUpdateDate:lastUpdateDate];
}];
}
completionBlock:completion];
}
- (void)clearWithProfileKey:(OWSAES256Key *)profileKey
dbConnection:(YapDatabaseConnection *)dbConnection
completion:(nullable OWSUserProfileCompletion)completion;
{
OWSAssert(profileKey);
[dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self applyChangeToSelfAndLatestCopy:transaction
changeBlock:^(OWSUserProfile *userProfile) {
[userProfile setProfileKey:profileKey];
[userProfile setProfileName:nil];
[userProfile setAvatarUrlPath:nil];
[userProfile setAvatarFileName:nil];
[userProfile setLastUpdateDate:nil];
}];
}
completionBlock:completion];
}
- (void)updateImmediatelyWithProfileKey:(OWSAES256Key *)profileKey
dbConnection:(YapDatabaseConnection *)dbConnection
completion:(nullable OWSUserProfileCompletion)completion;
{
OWSAssert(profileKey);
self.profileKey = profileKey;
[dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self applyChangeToSelfAndLatestCopy:transaction
changeBlock:^(OWSUserProfile *userProfile) {
[userProfile setProfileKey:profileKey];
}];
}
completionBlock:completion];
}
#pragma mark - Database Connection Accessors
- (YapDatabaseConnection *)dbReadConnection
{
OWSFail(@"%@ UserProfile should always use OWSProfileManager's database connection.", self.logTag);
return TSYapDatabaseObject.dbReadConnection;
}
+ (YapDatabaseConnection *)dbReadConnection
{
OWSFail(@"%@ UserProfile should always use OWSProfileManager's database connection.", self.logTag);
return TSYapDatabaseObject.dbReadConnection;
}
- (YapDatabaseConnection *)dbReadWriteConnection
{
OWSFail(@"%@ UserProfile should always use OWSProfileManager's database connection.", self.logTag);
return TSYapDatabaseObject.dbReadWriteConnection;
}
+ (YapDatabaseConnection *)dbReadWriteConnection
{
OWSFail(@"%@ UserProfile should always use OWSProfileManager's database connection.", self.logTag);
return TSYapDatabaseObject.dbReadWriteConnection;
}
@end
NS_ASSUME_NONNULL_END
Loading…
Cancel
Save