Move more work off the main thread.

// FREEBIE
This commit is contained in:
Matthew Chen 2017-09-28 10:01:17 -04:00
parent 80ae952716
commit 9573e0e16d
7 changed files with 193 additions and 212 deletions

View File

@ -495,7 +495,7 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68;
// This will save the message.
[message updateWithCustomMessage:NSLocalizedString(@"GROUP_CREATED", nil)];
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (model.groupImage) {
NSData *data = UIImagePNGRepresentation(model.groupImage);
DataSource *_Nullable dataSource =

View File

@ -206,45 +206,46 @@ NSString *const kNotificationsManagerNewMesssageSoundName = @"NewMessage.aifc";
#pragma mark - Signal Messages
- (void)notifyUserForErrorMessage:(TSErrorMessage *)message inThread:(TSThread *)thread {
OWSAssert([NSThread isMainThread]);
OWSAssert(message);
OWSAssert(thread);
if (thread.isMuted) {
return;
}
BOOL shouldPlaySound = [self shouldPlaySoundForNotification];
NSString *messageDescription = message.description;
if (([UIApplication sharedApplication].applicationState != UIApplicationStateActive) && messageDescription) {
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.userInfo = @{Signal_Thread_UserInfo_Key : thread.uniqueId};
if (shouldPlaySound) {
notification.soundName = kNotificationsManagerNewMesssageSoundName;
dispatch_async(dispatch_get_main_queue(), ^{
if (thread.isMuted) {
return;
}
NSString *alertBodyString = @"";
BOOL shouldPlaySound = [self shouldPlaySoundForNotification];
NSString *authorName = [thread name];
switch (self.notificationPreviewType) {
case NotificationNamePreview:
case NotificationNameNoPreview:
alertBodyString = [NSString stringWithFormat:@"%@: %@", authorName, messageDescription];
break;
case NotificationNoNameNoPreview:
alertBodyString = messageDescription;
break;
}
notification.alertBody = alertBodyString;
NSString *messageDescription = message.description;
[[PushManager sharedManager] presentNotification:notification checkForCancel:NO];
} else {
if (shouldPlaySound && [Environment.preferences soundInForeground]) {
AudioServicesPlayAlertSound(_newMessageSound);
if (([UIApplication sharedApplication].applicationState != UIApplicationStateActive) && messageDescription) {
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.userInfo = @{ Signal_Thread_UserInfo_Key : thread.uniqueId };
if (shouldPlaySound) {
notification.soundName = kNotificationsManagerNewMesssageSoundName;
}
NSString *alertBodyString = @"";
NSString *authorName = [thread name];
switch (self.notificationPreviewType) {
case NotificationNamePreview:
case NotificationNameNoPreview:
alertBodyString = [NSString stringWithFormat:@"%@: %@", authorName, messageDescription];
break;
case NotificationNoNameNoPreview:
alertBodyString = messageDescription;
break;
}
notification.alertBody = alertBodyString;
[[PushManager sharedManager] presentNotification:notification checkForCancel:NO];
} else {
if (shouldPlaySound && [Environment.preferences soundInForeground]) {
AudioServicesPlayAlertSound(_newMessageSound);
}
}
}
});
}
- (void)notifyUserForIncomingMessage:(TSIncomingMessage *)message
@ -255,83 +256,87 @@ NSString *const kNotificationsManagerNewMesssageSoundName = @"NewMessage.aifc";
OWSAssert(thread);
OWSAssert(contactsManager);
if (thread.isMuted) {
return;
}
BOOL shouldPlaySound = [self shouldPlaySoundForNotification];
NSString *messageDescription = message.description;
NSString *senderName = [contactsManager displayNameForPhoneIdentifier:message.authorId];
NSString *groupName = [thread.name stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if (groupName.length < 1) {
groupName = NSLocalizedString(@"NEW_GROUP_DEFAULT_TITLE", @"");
}
if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive && messageDescription) {
UILocalNotification *notification = [[UILocalNotification alloc] init];
if (shouldPlaySound) {
notification.soundName = kNotificationsManagerNewMesssageSoundName;
dispatch_async(dispatch_get_main_queue(), ^{
if (thread.isMuted) {
return;
}
switch (self.notificationPreviewType) {
case NotificationNamePreview: {
BOOL shouldPlaySound = [self shouldPlaySoundForNotification];
// Don't reply from lockscreen if anyone in this conversation is
// "no longer verified".
BOOL isNoLongerVerified = NO;
for (NSString *recipientId in thread.recipientIdentifiers) {
if ([OWSIdentityManager.sharedManager verificationStateForRecipientId:recipientId]
== OWSVerificationStateNoLongerVerified) {
isNoLongerVerified = YES;
break;
NSString *messageDescription = message.description;
NSString *senderName = [contactsManager displayNameForPhoneIdentifier:message.authorId];
NSString *groupName = [thread.name stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if (groupName.length < 1) {
groupName = NSLocalizedString(@"NEW_GROUP_DEFAULT_TITLE", @"");
}
if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive && messageDescription) {
UILocalNotification *notification = [[UILocalNotification alloc] init];
if (shouldPlaySound) {
notification.soundName = kNotificationsManagerNewMesssageSoundName;
}
switch (self.notificationPreviewType) {
case NotificationNamePreview: {
// Don't reply from lockscreen if anyone in this conversation is
// "no longer verified".
BOOL isNoLongerVerified = NO;
for (NSString *recipientId in thread.recipientIdentifiers) {
if ([OWSIdentityManager.sharedManager verificationStateForRecipientId:recipientId]
== OWSVerificationStateNoLongerVerified) {
isNoLongerVerified = YES;
break;
}
}
}
notification.category = (isNoLongerVerified ? Signal_Full_New_Message_Category_No_Longer_Verified
: Signal_Full_New_Message_Category);
notification.userInfo =
@{Signal_Thread_UserInfo_Key : thread.uniqueId, Signal_Message_UserInfo_Key : message.uniqueId};
notification.category = (isNoLongerVerified ? Signal_Full_New_Message_Category_No_Longer_Verified
: Signal_Full_New_Message_Category);
notification.userInfo = @{
Signal_Thread_UserInfo_Key : thread.uniqueId,
Signal_Message_UserInfo_Key : message.uniqueId
};
if ([thread isGroupThread]) {
NSString *threadName = [NSString stringWithFormat:@"\"%@\"", groupName];
// TODO: Format parameters might change order in l10n. We should use named parameters.
notification.alertBody =
[NSString stringWithFormat:NSLocalizedString(@"APN_MESSAGE_IN_GROUP_DETAILED", nil),
senderName,
threadName,
messageDescription];
} else {
notification.alertBody = [NSString stringWithFormat:@"%@: %@", senderName, messageDescription];
if ([thread isGroupThread]) {
NSString *threadName = [NSString stringWithFormat:@"\"%@\"", groupName];
// TODO: Format parameters might change order in l10n. We should use named parameters.
notification.alertBody =
[NSString stringWithFormat:NSLocalizedString(@"APN_MESSAGE_IN_GROUP_DETAILED", nil),
senderName,
threadName,
messageDescription];
} else {
notification.alertBody = [NSString stringWithFormat:@"%@: %@", senderName, messageDescription];
}
break;
}
break;
case NotificationNameNoPreview: {
notification.userInfo = @{ Signal_Thread_UserInfo_Key : thread.uniqueId };
if ([thread isGroupThread]) {
notification.alertBody = [NSString
stringWithFormat:@"%@ \"%@\"", NSLocalizedString(@"APN_MESSAGE_IN_GROUP", nil), groupName];
} else {
notification.alertBody = [NSString
stringWithFormat:@"%@ %@", NSLocalizedString(@"APN_MESSAGE_FROM", nil), senderName];
}
break;
}
case NotificationNoNameNoPreview:
notification.alertBody = NSLocalizedString(@"APN_Message", nil);
break;
default:
DDLogWarn(@"unknown notification preview type: %lu", (unsigned long)self.notificationPreviewType);
notification.alertBody = NSLocalizedString(@"APN_Message", nil);
break;
}
case NotificationNameNoPreview: {
notification.userInfo = @{Signal_Thread_UserInfo_Key : thread.uniqueId};
if ([thread isGroupThread]) {
notification.alertBody = [NSString
stringWithFormat:@"%@ \"%@\"", NSLocalizedString(@"APN_MESSAGE_IN_GROUP", nil), groupName];
} else {
notification.alertBody =
[NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"APN_MESSAGE_FROM", nil), senderName];
}
break;
}
case NotificationNoNameNoPreview:
notification.alertBody = NSLocalizedString(@"APN_Message", nil);
break;
default:
DDLogWarn(@"unknown notification preview type: %lu", (unsigned long)self.notificationPreviewType);
notification.alertBody = NSLocalizedString(@"APN_Message", nil);
break;
}
[[PushManager sharedManager] presentNotification:notification checkForCancel:YES];
} else {
if (shouldPlaySound && [Environment.preferences soundInForeground]) {
AudioServicesPlayAlertSound(_newMessageSound);
[[PushManager sharedManager] presentNotification:notification checkForCancel:YES];
} else {
if (shouldPlaySound && [Environment.preferences soundInForeground]) {
AudioServicesPlayAlertSound(_newMessageSound);
}
}
}
});
}
- (BOOL)shouldPlaySoundForNotification

View File

@ -183,7 +183,7 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin
forKey:kOWSBlockingManager_BlockedPhoneNumbersKey
inCollection:kOWSBlockingManager_BlockedPhoneNumbersCollection];
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (sendSyncMessage) {
[self sendBlockedPhoneNumbersMessage:blockedPhoneNumbers];
} else {
@ -238,9 +238,7 @@ NSString *const kOWSBlockingManager_SyncedBlockedPhoneNumbersKey = @"kOWSBlockin
NSSet *syncedBlockedPhoneNumberSet = [[NSSet alloc] initWithArray:(syncedBlockedPhoneNumbers ?: [NSArray new])];
if (![_blockedPhoneNumberSet isEqualToSet:syncedBlockedPhoneNumberSet]) {
DDLogInfo(@"%@ retrying sync of blocked phone numbers", self.tag);
dispatch_async(dispatch_get_main_queue(), ^{
[self sendBlockedPhoneNumbersMessage:self.blockedPhoneNumbers];
});
[self sendBlockedPhoneNumbersMessage:self.blockedPhoneNumbers];
}
}

View File

@ -495,11 +495,9 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
[messages addObject:message];
}
if (messages.count > 0) {
dispatch_async(dispatch_get_main_queue(), ^{
for (OWSVerificationStateSyncMessage *message in messages) {
[self sendSyncVerificationStateMessage:message];
}
});
for (OWSVerificationStateSyncMessage *message in messages) {
[self sendSyncVerificationStateMessage:message];
}
}
}
});
@ -509,7 +507,6 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
{
OWSAssert(message);
OWSAssert(message.verificationForRecipientId.length > 0);
OWSAssert([NSThread isMainThread]);
TSContactThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:message.verificationForRecipientId];
@ -519,20 +516,17 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
verificationStateSyncMessage:message];
[self.messageSender sendMessage:nullMessage
success:^{
dispatch_async(dispatch_get_main_queue(), ^{
DDLogInfo(@"%@ Successfully sent verification state NullMessage", self.tag);
[self.messageSender sendMessage:message
success:^{
DDLogInfo(@"%@ Successfully sent verification state sync message", self.tag);
DDLogInfo(@"%@ Successfully sent verification state NullMessage", self.tag);
[self.messageSender sendMessage:message
success:^{
DDLogInfo(@"%@ Successfully sent verification state sync message", self.tag);
// Record that this verification state was successfully synced.
[self clearSyncMessageForRecipientId:message.verificationForRecipientId];
}
failure:^(NSError *error) {
DDLogError(
@"%@ Failed to send verification state sync message with error: %@", self.tag, error);
}];
});
// Record that this verification state was successfully synced.
[self clearSyncMessageForRecipientId:message.verificationForRecipientId];
}
failure:^(NSError *error) {
DDLogError(@"%@ Failed to send verification state sync message with error: %@", self.tag, error);
}];
}
failure:^(NSError *_Nonnull error) {
DDLogError(@"%@ Failed to send verification state NullMessage with error: %@", self.tag, error);
@ -575,26 +569,28 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
}
NSData *identityKey = [rawIdentityKey removeKeyType];
switch (verified.state) {
case OWSSignalServiceProtosVerifiedStateDefault:
[self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateDefault
recipientId:recipientId
identityKey:identityKey
overwriteOnConflict:NO];
break;
case OWSSignalServiceProtosVerifiedStateVerified:
[self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateVerified
recipientId:recipientId
identityKey:identityKey
overwriteOnConflict:YES];
break;
case OWSSignalServiceProtosVerifiedStateUnverified:
OWSFail(@"Verification state sync message for recipientId: %@ has unexpected value: %@.",
recipientId,
OWSVerificationStateToString(OWSVerificationStateNoLongerVerified));
return;
}
[self fireIdentityStateChangeNotification];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
switch (verified.state) {
case OWSSignalServiceProtosVerifiedStateDefault:
[self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateDefault
recipientId:recipientId
identityKey:identityKey
overwriteOnConflict:NO];
break;
case OWSSignalServiceProtosVerifiedStateVerified:
[self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateVerified
recipientId:recipientId
identityKey:identityKey
overwriteOnConflict:YES];
break;
case OWSSignalServiceProtosVerifiedStateUnverified:
OWSFail(@"Verification state sync message for recipientId: %@ has unexpected value: %@.",
recipientId,
OWSVerificationStateToString(OWSVerificationStateNoLongerVerified));
return;
}
[self fireIdentityStateChangeNotification];
});
}
- (void)tryToApplyVerificationStateFromSyncMessage:(OWSVerificationState)verificationState

View File

@ -305,10 +305,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)notifyForErrorMessage:(TSErrorMessage *)errorMessage withEnvelope:(OWSSignalServiceProtosEnvelope *)envelope
{
TSThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:envelope.source];
dispatch_async(dispatch_get_main_queue(), ^{
[[TextSecureKitEnv sharedEnv].notificationsManager notifyUserForErrorMessage:errorMessage
inThread:contactThread];
});
[[TextSecureKitEnv sharedEnv].notificationsManager notifyUserForErrorMessage:errorMessage inThread:contactThread];
}
#pragma mark - Logging

View File

@ -604,9 +604,8 @@ NS_ASSUME_NONNULL_BEGIN
DDLogWarn(@"%@ ignoring unsupported sync request message", self.tag);
}
} else if (syncMessage.hasBlocked) {
// TODO: Do this synchronously.
dispatch_async(dispatch_get_main_queue(), ^{
NSArray<NSString *> *blockedPhoneNumbers = [syncMessage.blocked.numbers copy];
NSArray<NSString *> *blockedPhoneNumbers = [syncMessage.blocked.numbers copy];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[_blockingManager setBlockedPhoneNumbers:blockedPhoneNumbers sendSyncMessage:NO];
});
} else if (syncMessage.read.count > 0) {
@ -616,10 +615,7 @@ NS_ASSUME_NONNULL_BEGIN
transaction:transaction];
} else if (syncMessage.hasVerified) {
DDLogInfo(@"%@ Received verification state for %@", self.tag, syncMessage.verified.destination);
// TODO: Do this synchronously.
dispatch_async(dispatch_get_main_queue(), ^{
[self.identityManager processIncomingSyncMessage:syncMessage.verified];
});
[self.identityManager processIncomingSyncMessage:syncMessage.verified];
} else {
DDLogWarn(@"%@ Ignoring unsupported sync message.", self.tag);
}
@ -944,18 +940,15 @@ NS_ASSUME_NONNULL_BEGIN
[OWSReadReceiptManager.sharedManager applyEarlyReadReceiptsForIncomingMessage:incomingMessage
transaction:transaction];
// TODO: Do this synchronously.
dispatch_async(dispatch_get_main_queue(), ^{
[OWSDisappearingMessagesJob becomeConsistentWithConfigurationForMessage:incomingMessage
contactsManager:self.contactsManager];
[OWSDisappearingMessagesJob becomeConsistentWithConfigurationForMessage:incomingMessage
contactsManager:self.contactsManager];
// Update thread preview in inbox
[thread touch];
// Update thread preview in inbox
[thread touchWithTransaction:transaction];
[[TextSecureKitEnv sharedEnv].notificationsManager notifyUserForIncomingMessage:incomingMessage
inThread:thread
contactsManager:self.contactsManager];
});
[[TextSecureKitEnv sharedEnv].notificationsManager notifyUserForIncomingMessage:incomingMessage
inThread:thread
contactsManager:self.contactsManager];
}
return incomingMessage;

View File

@ -178,7 +178,7 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
object:nil];
// Try to start processing.
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self scheduleProcessing];
});
@ -198,33 +198,30 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
// Schedules a processing pass, unless one is already scheduled.
- (void)scheduleProcessing
{
DispatchMainThreadSafe(^{
@synchronized(self)
{
if ([TSDatabaseView hasPendingViewRegistrations]) {
DDLogInfo(
@"%@ Deferring read receipt processing due to pending database view registrations.", self.tag);
return;
}
if (self.isProcessing) {
return;
}
self.isProcessing = YES;
// Process read receipts every N seconds.
//
// We want a value high enough to allow us to effectively de-duplicate,
// read receipts without being so high that we risk not sending read
// receipts due to app exit.
const CGFloat kProcessingFrequencySeconds = 3.f;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kProcessingFrequencySeconds * NSEC_PER_SEC)),
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
[self process];
});
@synchronized(self)
{
if ([TSDatabaseView hasPendingViewRegistrations]) {
DDLogInfo(@"%@ Deferring read receipt processing due to pending database view registrations.", self.tag);
return;
}
});
if (self.isProcessing) {
return;
}
self.isProcessing = YES;
// Process read receipts every N seconds.
//
// We want a value high enough to allow us to effectively de-duplicate,
// read receipts without being so high that we risk not sending read
// receipts due to app exit.
const CGFloat kProcessingFrequencySeconds = 3.f;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kProcessingFrequencySeconds * NSEC_PER_SEC)),
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
[self process];
});
}
}
- (void)process
@ -241,17 +238,15 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
OWSReadReceiptsForLinkedDevicesMessage *message =
[[OWSReadReceiptsForLinkedDevicesMessage alloc] initWithReadReceipts:readReceiptsForLinkedDevices];
dispatch_async(dispatch_get_main_queue(), ^{
[self.messageSender sendMessage:message
success:^{
DDLogInfo(@"%@ Successfully sent %zd read receipt to linked devices.",
self.tag,
readReceiptsForLinkedDevices.count);
}
failure:^(NSError *error) {
DDLogError(@"%@ Failed to send read receipt to linked devices with error: %@", self.tag, error);
}];
});
[self.messageSender sendMessage:message
success:^{
DDLogInfo(@"%@ Successfully sent %zd read receipt to linked devices.",
self.tag,
readReceiptsForLinkedDevices.count);
}
failure:^(NSError *error) {
DDLogError(@"%@ Failed to send read receipt to linked devices with error: %@", self.tag, error);
}];
}
NSArray<OWSReadReceipt *> *readReceiptsToSend = [self.toLinkedDevicesReadReceiptMap allValues];
@ -266,17 +261,14 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
[[OWSReadReceiptsForSenderMessage alloc] initWithThread:thread
messageTimestamps:timestamps.allObjects];
dispatch_async(dispatch_get_main_queue(), ^{
[self.messageSender sendMessage:message
success:^{
DDLogInfo(@"%@ Successfully sent %zd read receipts to sender.",
self.tag,
readReceiptsToSend.count);
}
failure:^(NSError *error) {
DDLogError(@"%@ Failed to send read receipts to sender with error: %@", self.tag, error);
}];
});
[self.messageSender sendMessage:message
success:^{
DDLogInfo(
@"%@ Successfully sent %zd read receipts to sender.", self.tag, readReceiptsToSend.count);
}
failure:^(NSError *error) {
DDLogError(@"%@ Failed to send read receipts to sender with error: %@", self.tag, error);
}];
}
[self.toSenderReadReceiptMap removeAllObjects];
}