parent
6b5883dc10
commit
6e2d9c8141
|
@ -54,10 +54,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
OWSAssert(flippedKey.length == currentKey.length);
|
||||
[identityManager saveRemoteIdentity:flippedKey recipientId:recipientId];
|
||||
}],
|
||||
[OWSTableItem itemWithTitle:@"Set Verification State"
|
||||
actionBlock:^{
|
||||
[DebugUISessionState presentVerificationStatePickerForContactThread:thread];
|
||||
}],
|
||||
[OWSTableItem itemWithTitle:@"Delete all sessions"
|
||||
actionBlock:^{
|
||||
dispatch_async([OWSDispatch sessionStoreQueue], ^{
|
||||
|
@ -81,56 +77,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
]];
|
||||
}
|
||||
|
||||
+ (void)presentVerificationStatePickerForContactThread:(TSContactThread *)contactThread
|
||||
{
|
||||
DDLogError(@"%@ Choosing verification state.", self.logTag);
|
||||
|
||||
NSString *title = [NSString stringWithFormat:@"Choose verification state for %@", contactThread.name];
|
||||
UIAlertController *alertController =
|
||||
[UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleActionSheet];
|
||||
|
||||
NSString *recipientId = [contactThread contactIdentifier];
|
||||
OWSIdentityManager *identityManger = [OWSIdentityManager sharedManager];
|
||||
|
||||
[alertController addAction:[UIAlertAction actionWithTitle:@"Default"
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
NSData *identityKey =
|
||||
[identityManger identityKeyForRecipientId:recipientId];
|
||||
[[OWSIdentityManager sharedManager]
|
||||
setVerificationState:OWSVerificationStateDefault
|
||||
identityKey:identityKey
|
||||
recipientId:recipientId
|
||||
isUserInitiatedChange:NO];
|
||||
}]];
|
||||
[alertController addAction:[UIAlertAction actionWithTitle:@"Verified"
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
NSData *identityKey =
|
||||
[identityManger identityKeyForRecipientId:recipientId];
|
||||
[[OWSIdentityManager sharedManager]
|
||||
setVerificationState:OWSVerificationStateVerified
|
||||
identityKey:identityKey
|
||||
recipientId:recipientId
|
||||
isUserInitiatedChange:NO];
|
||||
}]];
|
||||
[alertController addAction:[UIAlertAction actionWithTitle:@"No Longer Verified"
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
NSData *identityKey =
|
||||
[identityManger identityKeyForRecipientId:recipientId];
|
||||
[[OWSIdentityManager sharedManager]
|
||||
setVerificationState:OWSVerificationStateNoLongerVerified
|
||||
identityKey:identityKey
|
||||
recipientId:recipientId
|
||||
isUserInitiatedChange:NO];
|
||||
}]];
|
||||
|
||||
[[UIApplication sharedApplication].frontmostViewController presentViewController:alertController
|
||||
animated:YES
|
||||
completion:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -1540,6 +1540,9 @@
|
|||
/* action sheet item */
|
||||
"SHARE_ACTION_TWEET" = "Twitter";
|
||||
|
||||
/* alert body when sharing filefailed because of untrusted/changed identity keys */
|
||||
"SHARE_EXTENSION_FAILED_SENDING_BECAUSE_UNTRUSTED_IDENTITY_KEY" = "Your safety number with %@ has recently changed. You may wish to verify it in the main app before resending.";
|
||||
|
||||
/* Indicates that the share extension is still loading. */
|
||||
"SHARE_EXTENSION_LOADING" = "Loading...";
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#import "UIFont+OWS.h"
|
||||
#import "UIView+OWS.h"
|
||||
#import <SignalMessaging/SignalMessaging-Swift.h>
|
||||
#import <SignalServiceKit/OWSDispatch.h>
|
||||
#import <SignalServiceKit/OWSError.h>
|
||||
#import <SignalServiceKit/OWSMessageSender.h>
|
||||
#import <SignalServiceKit/TSThread.h>
|
||||
|
||||
|
@ -124,26 +126,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
OWSAssert(thread);
|
||||
self.thread = thread;
|
||||
|
||||
__weak typeof(self) weakSelf = self;
|
||||
|
||||
// FIXME SHARINGEXTENSION
|
||||
// Handling safety number changes brings in a lot of machinery.
|
||||
// How do we want to handle this?
|
||||
// e.g. fingerprint scanning, etc. in the SAE or just redirect the user to the main app?
|
||||
// BOOL didShowSNAlert =
|
||||
// [SafetyNumberConfirmationAlert presentAlertIfNecessaryWithRecipientIds:thread.recipientIdentifiers
|
||||
// confirmationText:[SafetyNumberStrings
|
||||
// confirmSendButton]
|
||||
// contactsManager:self.contactsManager
|
||||
// completion:^(BOOL didConfirm) {
|
||||
// if (didConfirm) {
|
||||
// [weakSelf threadWasSelected:thread];
|
||||
// }
|
||||
// }];
|
||||
// if (didShowSNAlert) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
AttachmentApprovalViewController *approvalVC =
|
||||
[[AttachmentApprovalViewController alloc] initWithAttachment:self.attachment delegate:self];
|
||||
|
||||
|
@ -211,7 +193,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
}
|
||||
#endif
|
||||
|
||||
void (^sendCompletion)(NSError *_Nullable) = ^(NSError *_Nullable error) {
|
||||
void (^sendCompletion)(NSError *_Nullable, TSOutgoingMessage *message) = ^(
|
||||
NSError *_Nullable error, TSOutgoingMessage *message) {
|
||||
AssertIsOnMainThread();
|
||||
|
||||
if (error) {
|
||||
|
@ -220,7 +203,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
completion:^(void) {
|
||||
DDLogInfo(@"%@ Sending attachment failed with error: %@", self.logTag, error);
|
||||
[self showSendFailureAlertWithError:error
|
||||
attachment:attachment
|
||||
message:message
|
||||
fromViewController:fromViewController];
|
||||
}];
|
||||
return;
|
||||
|
@ -233,44 +216,183 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
[fromViewController presentViewController:progressAlert
|
||||
animated:YES
|
||||
completion:^(void) {
|
||||
TSOutgoingMessage *outgoingMessage =
|
||||
__block TSOutgoingMessage *outgoingMessage =
|
||||
[ThreadUtil sendMessageWithAttachment:self.attachment
|
||||
inThread:self.thread
|
||||
messageSender:self.messageSender
|
||||
completion:sendCompletion];
|
||||
completion:^(NSError *_Nullable error) {
|
||||
sendCompletion(error, outgoingMessage);
|
||||
}];
|
||||
|
||||
self.outgoingMessage = outgoingMessage;
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)showSendFailureAlertWithError:(NSError *)error
|
||||
attachment:(SignalAttachment *)attachment
|
||||
message:(TSOutgoingMessage *)message
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
OWSAssert(error);
|
||||
OWSAssert(message);
|
||||
OWSAssert(fromViewController);
|
||||
|
||||
NSString *failureTitle = NSLocalizedString(@"SHARE_EXTENSION_SENDING_FAILURE_TITLE", @"Alert title");
|
||||
|
||||
UIAlertController *failureAlert = [UIAlertController alertControllerWithTitle:failureTitle
|
||||
message:error.localizedDescription
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
if (error.code == OWSErrorCodeUntrustedIdentity) {
|
||||
NSString *_Nullable untrustedRecipientId = error.userInfo[OWSErrorRecipientIdentifierKey];
|
||||
|
||||
UIAlertAction *failureCancelAction = [UIAlertAction actionWithTitle:[CommonStrings cancelButton]
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
[self.shareViewDelegate shareViewWasCancelled];
|
||||
}];
|
||||
[failureAlert addAction:failureCancelAction];
|
||||
NSString *failureFormat = NSLocalizedString(@"SHARE_EXTENSION_FAILED_SENDING_BECAUSE_UNTRUSTED_IDENTITY_KEY",
|
||||
@"alert body when sharing filefailed because of untrusted/changed identity keys");
|
||||
|
||||
UIAlertAction *retryAction =
|
||||
[UIAlertAction actionWithTitle:[CommonStrings retryButton]
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *action) {
|
||||
[self tryToSendAttachment:attachment fromViewController:fromViewController];
|
||||
}];
|
||||
[failureAlert addAction:retryAction];
|
||||
NSString *displayName = [self.contactsManager displayNameForPhoneIdentifier:untrustedRecipientId];
|
||||
NSString *failureMessage = [NSString stringWithFormat:failureFormat, displayName];
|
||||
|
||||
[fromViewController presentViewController:failureAlert animated:YES completion:nil];
|
||||
UIAlertController *failureAlert = [UIAlertController alertControllerWithTitle:failureTitle
|
||||
message:failureMessage
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction *failureCancelAction = [UIAlertAction actionWithTitle:[CommonStrings cancelButton]
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
[self.shareViewDelegate shareViewWasCancelled];
|
||||
}];
|
||||
[failureAlert addAction:failureCancelAction];
|
||||
|
||||
if (untrustedRecipientId.length > 0) {
|
||||
UIAlertAction *confirmAction =
|
||||
[UIAlertAction actionWithTitle:[SafetyNumberStrings confirmSendButton]
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *action) {
|
||||
[self confirmIdentityAndResendMessage:message
|
||||
recipientId:untrustedRecipientId
|
||||
fromViewController:fromViewController];
|
||||
}];
|
||||
|
||||
[failureAlert addAction:confirmAction];
|
||||
} else {
|
||||
// This shouldn't happen, but if it does we won't offer the user the ability to confirm.
|
||||
// They may have to return to the main app to accept the identity change.
|
||||
OWSFail(@"%@ Untrusted recipient error is missing recipient id.", self.logTag);
|
||||
}
|
||||
|
||||
[fromViewController presentViewController:failureAlert animated:YES completion:nil];
|
||||
} else {
|
||||
// Non-identity failure, e.g. network offline, rate limit
|
||||
|
||||
UIAlertController *failureAlert = [UIAlertController alertControllerWithTitle:failureTitle
|
||||
message:error.localizedDescription
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction *failureCancelAction = [UIAlertAction actionWithTitle:[CommonStrings cancelButton]
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
[self.shareViewDelegate shareViewWasCancelled];
|
||||
}];
|
||||
[failureAlert addAction:failureCancelAction];
|
||||
|
||||
UIAlertAction *retryAction =
|
||||
[UIAlertAction actionWithTitle:[CommonStrings retryButton]
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *action) {
|
||||
[self resendMessage:message fromViewController:fromViewController];
|
||||
}];
|
||||
|
||||
[failureAlert addAction:retryAction];
|
||||
[fromViewController presentViewController:failureAlert animated:YES completion:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)confirmIdentityAndResendMessage:(TSOutgoingMessage *)message
|
||||
recipientId:(NSString *)recipientId
|
||||
fromViewController:(UIViewController *)fromViewController
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
OWSAssert(message);
|
||||
OWSAssert(recipientId.length > 0);
|
||||
OWSAssert(fromViewController);
|
||||
|
||||
DDLogDebug(@"%@ Confirming identity for recipient: %@", self.logTag, recipientId);
|
||||
|
||||
dispatch_async([OWSDispatch sessionStoreQueue], ^(void) {
|
||||
OWSVerificationState verificationState =
|
||||
[[OWSIdentityManager sharedManager] verificationStateForRecipientId:recipientId];
|
||||
switch (verificationState) {
|
||||
case OWSVerificationStateVerified: {
|
||||
OWSFail(@"%@ Shouldn't need to confirm identity if it was already verified", self.logTag);
|
||||
break;
|
||||
}
|
||||
case OWSVerificationStateDefault: {
|
||||
// If we learned of a changed SN during send, then we've already recorded the new identity
|
||||
// and there's nothing else we need to do for the resend to succeed.
|
||||
// We don't want to redundantly set status to "default" because we would create a
|
||||
// "You marked Alice as unverified" notice, which wouldn't make sense if Alice was never
|
||||
// marked as "Verified".
|
||||
DDLogInfo(@"%@ recipient has acceptable verification status. Next send will succeed.", self.logTag);
|
||||
break;
|
||||
}
|
||||
case OWSVerificationStateNoLongerVerified: {
|
||||
DDLogInfo(@"%@ marked recipient: %@ as default verification status.", self.logTag, recipientId);
|
||||
NSData *identityKey = [[OWSIdentityManager sharedManager] identityKeyForRecipientId:recipientId];
|
||||
OWSAssert(identityKey);
|
||||
[[OWSIdentityManager sharedManager] setVerificationState:OWSVerificationStateDefault
|
||||
identityKey:identityKey
|
||||
recipientId:recipientId
|
||||
isUserInitiatedChange:YES];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^(void) {
|
||||
[self resendMessage:message fromViewController:fromViewController];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
- (void)resendMessage:(TSOutgoingMessage *)message fromViewController:(UIViewController *)fromViewController
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
OWSAssert(message);
|
||||
OWSAssert(fromViewController);
|
||||
|
||||
NSString *progressTitle = NSLocalizedString(@"SHARE_EXTENSION_SENDING_IN_PROGRESS_TITLE", @"Alert title");
|
||||
UIAlertController *progressAlert = [UIAlertController alertControllerWithTitle:progressTitle
|
||||
message:nil
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction *progressCancelAction = [UIAlertAction actionWithTitle:[CommonStrings cancelButton]
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
[self.shareViewDelegate shareViewWasCancelled];
|
||||
}];
|
||||
[progressAlert addAction:progressCancelAction];
|
||||
|
||||
[fromViewController
|
||||
presentViewController:progressAlert
|
||||
animated:YES
|
||||
completion:^(void) {
|
||||
[self.messageSender enqueueMessage:message
|
||||
success:^(void) {
|
||||
DDLogInfo(@"%@ Resending attachment succeeded.", self.logTag);
|
||||
dispatch_async(dispatch_get_main_queue(), ^(void) {
|
||||
[self.shareViewDelegate shareViewWasCompleted];
|
||||
});
|
||||
}
|
||||
failure:^(NSError *error) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^(void) {
|
||||
[fromViewController
|
||||
dismissViewControllerAnimated:YES
|
||||
completion:^(void) {
|
||||
DDLogInfo(@"%@ Sending attachment failed with error: %@",
|
||||
self.logTag,
|
||||
error);
|
||||
[self showSendFailureAlertWithError:error
|
||||
message:message
|
||||
fromViewController:fromViewController];
|
||||
}];
|
||||
});
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)attachmentUploadProgress:(NSNotification *)notification
|
||||
|
|
|
@ -861,7 +861,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
NSString *localizedErrorDescription =
|
||||
[NSString stringWithFormat:localizedErrorDescriptionFormat,
|
||||
[self.contactsManager displayNameForPhoneIdentifier:recipient.recipientId]];
|
||||
NSError *error = OWSErrorWithCodeDescription(OWSErrorCodeUntrustedIdentityKey, localizedErrorDescription);
|
||||
NSError *error = OWSErrorMakeUntrustedIdentityError(localizedErrorDescription, recipient.recipientId);
|
||||
|
||||
// Key will continue to be unaccepted, so no need to retry. It'll only cause us to hit the Pre-Key request
|
||||
// rate limit
|
||||
|
@ -869,7 +869,13 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
// Avoid the "Too many failures with this contact" error rate limiting.
|
||||
[error setIsFatal:YES];
|
||||
|
||||
PreKeyBundle *newKeyBundle = exception.userInfo[TSInvalidPreKeyBundleKey];
|
||||
PreKeyBundle *_Nullable newKeyBundle = exception.userInfo[TSInvalidPreKeyBundleKey];
|
||||
if (newKeyBundle == nil) {
|
||||
OWSProdFail([OWSAnalyticsEvents messageSenderErrorMissingNewPreKeyBundle]);
|
||||
failureHandler(error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (![newKeyBundle isKindOfClass:[PreKeyBundle class]]) {
|
||||
OWSProdFail([OWSAnalyticsEvents messageSenderErrorUnexpectedKeyBundle]);
|
||||
failureHandler(error);
|
||||
|
|
|
@ -10,6 +10,12 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
// The code between these markers is code-generated by:
|
||||
// SignalServiceKit/Utilities/extract_analytics_event_names.py
|
||||
// To add an event, insert your logging event as a string e.g.:
|
||||
//
|
||||
// OWSProdFail(@"messageSenderErrorMissingNewPreKeyBundle");
|
||||
//
|
||||
// Then run SignalServiceKit/Utilities/extract_analytics_event_names.py, which
|
||||
// will extract the string into a named method in this class.
|
||||
#pragma mark - Code Generation Marker
|
||||
|
||||
+ (NSString *)accountsErrorRegisterPushTokensFailed;
|
||||
|
@ -96,6 +102,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
+ (NSString *)errorUpdateAttributesRequestFailed;
|
||||
|
||||
+ (NSString *)messageSenderErrorMissingNewPreKeyBundle;
|
||||
|
||||
+ (NSString *)messageManagerErrorCallMessageNoActionablePayload;
|
||||
|
||||
+ (NSString *)messageManagerErrorCorruptMessage;
|
||||
|
|
|
@ -222,6 +222,11 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
return @"error_update_attributes_request_failed";
|
||||
}
|
||||
|
||||
+ (NSString *)messageSenderErrorMissingNewPreKeyBundle
|
||||
{
|
||||
return @"messageSenderErrorMissingNewPreKeyBundle";
|
||||
}
|
||||
|
||||
+ (NSString *)messageManagerErrorCallMessageNoActionablePayload
|
||||
{
|
||||
return @"message_manager_error_call_message_no_actionable_payload";
|
||||
|
|
|
@ -13,7 +13,7 @@ typedef NS_ENUM(NSInteger, OWSErrorCode) {
|
|||
OWSErrorCodeFailedToEncodeJson = 14,
|
||||
OWSErrorCodeFailedToDecodeQR = 15,
|
||||
OWSErrorCodePrivacyVerificationFailure = 20,
|
||||
OWSErrorCodeUntrustedIdentityKey = 25,
|
||||
OWSErrorCodeUntrustedIdentity = 25,
|
||||
OWSErrorCodeFailedToSendOutgoingMessage = 30,
|
||||
OWSErrorCodeFailedToDecryptMessage = 100,
|
||||
OWSErrorCodeFailedToEncryptMessage = 110,
|
||||
|
@ -29,7 +29,10 @@ typedef NS_ENUM(NSInteger, OWSErrorCode) {
|
|||
OWSErrorCodeMessageDeletedBeforeSent = 777410,
|
||||
};
|
||||
|
||||
extern NSString *const OWSErrorRecipientIdentifierKey;
|
||||
|
||||
extern NSError *OWSErrorWithCodeDescription(OWSErrorCode code, NSString *description);
|
||||
extern NSError *OWSErrorMakeUntrustedIdentityError(NSString *description, NSString *recipientId);
|
||||
extern NSError *OWSErrorMakeUnableToProcessServerResponseError(void);
|
||||
extern NSError *OWSErrorMakeFailedToSendOutgoingMessageError(void);
|
||||
extern NSError *OWSErrorMakeNoSuchSignalRecipientError(void);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NSString *const OWSSignalServiceKitErrorDomain = @"OWSSignalServiceKitErrorDomain";
|
||||
NSString *const OWSErrorRecipientIdentifierKey = @"OWSErrorKeyRecipientIdentifier";
|
||||
|
||||
NSError *OWSErrorWithCodeDescription(OWSErrorCode code, NSString *description)
|
||||
{
|
||||
|
@ -40,6 +41,14 @@ NSError *OWSErrorMakeAssertionError()
|
|||
NSLocalizedString(@"ERROR_DESCRIPTION_UNKNOWN_ERROR", @"Worst case generic error message"));
|
||||
}
|
||||
|
||||
NSError *OWSErrorMakeUntrustedIdentityError(NSString *description, NSString *recipientId)
|
||||
{
|
||||
return [NSError
|
||||
errorWithDomain:OWSSignalServiceKitErrorDomain
|
||||
code:OWSErrorCodeUntrustedIdentity
|
||||
userInfo:@{ NSLocalizedDescriptionKey : description, OWSErrorRecipientIdentifierKey : recipientId }];
|
||||
}
|
||||
|
||||
NSError *OWSErrorMakeMessageSendDisabledDueToPreKeyUpdateFailuresError()
|
||||
{
|
||||
return OWSErrorWithCodeDescription(OWSErrorCodeMessageSendDisabledDueToPreKeyUpdateFailures,
|
||||
|
|
Loading…
Reference in New Issue