Replace decryption errors with single 'session refresh' message

This commit is contained in:
Nora Trapp 2021-01-12 16:31:35 -08:00
parent 122edf4c6e
commit 806dbd7257
12 changed files with 332 additions and 13 deletions

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "chat-session-refresh.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,236 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 5.900002 15.000000 cm
0.776471 0.776471 0.776471 scn
33.400002 79.900002 m
7.000000 80.000000 l
3.200000 80.000000 0.100000 76.900002 0.100000 73.099998 c
0.000000 7.000000 l
0.000000 3.199997 3.100000 0.099998 6.900000 0.099998 c
33.199997 0.000000 l
36.999996 0.000000 40.099998 3.099998 40.099998 6.900002 c
40.300003 73.000000 l
40.300003 76.800003 37.200001 79.900002 33.400002 79.900002 c
h
36.900002 6.900002 m
36.900002 4.900002 35.199997 3.199997 33.199997 3.199997 c
6.800001 3.300003 l
4.800001 3.300003 3.100000 5.000000 3.100000 7.000000 c
3.200001 73.099998 l
3.200001 75.099998 4.900000 76.800003 6.900000 76.800003 c
33.300003 76.699997 l
35.300003 76.699997 37.000000 75.000000 37.000000 73.000000 c
36.900002 6.900002 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 153.899994 15.000000 cm
0.776471 0.776471 0.776471 scn
33.400009 79.900002 m
7.000000 80.000000 l
3.200000 80.000000 0.100006 76.900002 0.100006 73.099998 c
0.000000 7.000000 l
0.000000 3.199997 3.100009 0.099998 6.900009 0.099998 c
33.300003 0.000000 l
37.100002 0.000000 40.200012 3.099998 40.200012 6.900002 c
40.300003 73.000000 l
40.300003 76.800003 37.200008 79.900002 33.400009 79.900002 c
h
36.900009 6.900002 m
36.900009 4.900002 35.200012 3.199997 33.200012 3.199997 c
6.800003 3.300003 l
4.800003 3.300003 3.100006 5.000000 3.100006 7.000000 c
3.200012 73.099998 l
3.200012 75.099998 4.900009 76.800003 6.900009 76.800003 c
33.300003 76.699997 l
35.300003 76.699997 37.000000 75.000000 37.000000 73.000000 c
36.900009 6.900002 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 124.000000 52.000000 cm
0.517647 0.517647 0.517647 scn
4.000000 2.000000 m
4.000000 0.895431 3.104569 0.000000 2.000000 0.000000 c
0.895431 0.000000 0.000000 0.895431 0.000000 2.000000 c
0.000000 3.104569 0.895431 4.000000 2.000000 4.000000 c
3.104569 4.000000 4.000000 3.104569 4.000000 2.000000 c
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 134.000000 52.000000 cm
0.517647 0.517647 0.517647 scn
4.000000 2.000000 m
4.000000 0.895431 3.104569 0.000000 2.000000 0.000000 c
0.895431 0.000000 0.000000 0.895431 0.000000 2.000000 c
0.000000 3.104569 0.895431 4.000000 2.000000 4.000000 c
3.104569 4.000000 4.000000 3.104569 4.000000 2.000000 c
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 144.000000 52.000000 cm
0.517647 0.517647 0.517647 scn
4.000000 2.000000 m
4.000000 0.895431 3.104569 0.000000 2.000000 0.000000 c
0.895431 0.000000 0.000000 0.895431 0.000000 2.000000 c
0.000000 3.104569 0.895431 4.000000 2.000000 4.000000 c
3.104569 4.000000 4.000000 3.104569 4.000000 2.000000 c
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 52.000000 52.000000 cm
0.517647 0.517647 0.517647 scn
4.000000 2.000000 m
4.000000 0.895431 3.104569 0.000000 2.000000 0.000000 c
0.895431 0.000000 0.000000 0.895431 0.000000 2.000000 c
0.000000 3.104569 0.895431 4.000000 2.000000 4.000000 c
3.104569 4.000000 4.000000 3.104569 4.000000 2.000000 c
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 62.000000 52.000000 cm
0.517647 0.517647 0.517647 scn
4.000000 2.000000 m
4.000000 0.895431 3.104569 0.000000 2.000000 0.000000 c
0.895431 0.000000 0.000000 0.895431 0.000000 2.000000 c
0.000000 3.104569 0.895431 4.000000 2.000000 4.000000 c
3.104569 4.000000 4.000000 3.104569 4.000000 2.000000 c
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 72.000000 52.000000 cm
0.517647 0.517647 0.517647 scn
4.000000 2.000000 m
4.000000 0.895431 3.104569 0.000000 2.000000 0.000000 c
0.895431 0.000000 0.000000 0.895431 0.000000 2.000000 c
0.000000 3.104569 0.895431 4.000000 2.000000 4.000000 c
3.104569 4.000000 4.000000 3.104569 4.000000 2.000000 c
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 82.000000 36.000000 cm
0.172549 0.419608 0.929412 scn
36.000000 18.000000 m
36.000000 8.058874 27.941126 0.000000 18.000000 0.000000 c
8.058874 0.000000 0.000000 8.058874 0.000000 18.000000 c
0.000000 27.941126 8.058874 36.000000 18.000000 36.000000 c
27.941126 36.000000 36.000000 27.941126 36.000000 18.000000 c
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 90.625801 44.377914 cm
1.000000 1.000000 1.000000 scn
18.754196 9.622087 m
18.767508 7.119224 17.787357 4.713304 16.028826 2.932274 c
14.270293 1.151245 11.877027 0.140591 9.374196 0.122086 c
7.817568 0.142702 6.289860 0.545544 4.925466 1.295172 c
3.561071 2.044800 2.401806 3.118246 1.549652 4.421069 c
0.697498 5.723892 0.178571 7.216168 0.038522 8.766621 c
-0.101526 10.317073 0.141595 11.878184 0.746499 13.312620 c
1.351403 14.747056 2.299551 16.010857 3.507533 16.992842 c
4.715514 17.974827 6.146309 18.644903 7.674047 18.944122 c
9.201785 19.243341 10.779646 19.162533 12.268823 18.708807 c
13.757999 18.255081 15.112855 17.442341 16.214197 16.342087 c
17.214197 15.342086 l
16.864197 16.642086 l
16.864197 19.062086 l
18.374197 19.062086 l
18.374197 13.122087 l
12.374196 13.122087 l
12.374196 14.622087 l
14.764195 14.622087 l
16.184196 14.242086 l
15.184196 15.242086 l
14.069366 16.370098 12.644415 17.141298 11.090346 17.457726 c
9.536278 17.774155 7.923225 17.621531 6.456084 17.019241 c
4.988943 16.416952 3.733922 15.392179 2.850443 14.075092 c
1.966963 12.758005 1.494893 11.208042 1.494196 9.622087 c
1.494196 8.587270 1.698018 7.562587 2.094025 6.606541 c
2.490032 5.650495 3.070469 4.781810 3.802195 4.050084 c
4.533920 3.318358 5.402605 2.737923 6.358651 2.341915 c
7.314696 1.945908 8.339379 1.742085 9.374196 1.742085 c
10.409013 1.742085 11.433697 1.945908 12.389742 2.341915 c
13.345787 2.737923 14.214473 3.318358 14.946198 4.050084 c
15.677924 4.781810 16.258360 5.650495 16.654367 6.606541 c
17.050375 7.562587 17.254196 8.587270 17.254196 9.622087 c
18.754196 9.622087 l
h
f
n
Q
endstream
endobj
3 0 obj
5681
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 200.000000 110.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Type /Catalog
/Pages 5 0 R
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000005771 00000 n
0000005794 00000 n
0000005969 00000 n
0000006043 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
6102
%%EOF

View File

@ -488,6 +488,8 @@ extension ColorPickerView: CVComponentDelegate {
func cvc_didTapCorruptedMessage(_ message: TSErrorMessage) {}
func cvc_didTapSessionRefreshMessage(_ message: TSErrorMessage) {}
func cvc_didTapResendGroupUpdateForErrorMessage(_ errorMessage: TSErrorMessage) {}
func cvc_didTapShowFingerprint(_ address: SignalServiceAddress) {}

View File

@ -118,6 +118,9 @@ public protocol CVComponentDelegate {
@objc
func cvc_didTapCorruptedMessage(_ message: TSErrorMessage)
@objc
func cvc_didTapSessionRefreshMessage(_ message: TSErrorMessage)
// See: resendGroupUpdate
@objc
func cvc_didTapResendGroupUpdateForErrorMessage(_ errorMessage: TSErrorMessage)
@ -177,6 +180,7 @@ struct CVMessageAction: Equatable {
case cvc_didTapNonBlockingIdentityChange(address: SignalServiceAddress)
case cvc_didTapInvalidIdentityKeyErrorMessage(errorMessage: TSInvalidIdentityKeyErrorMessage)
case cvc_didTapCorruptedMessage(errorMessage: TSErrorMessage)
case cvc_didTapSessionRefreshMessage(errorMessage: TSErrorMessage)
case cvc_didTapResendGroupUpdate(errorMessage: TSErrorMessage)
case cvc_didTapShowGroupMigrationLearnMoreActionSheet(infoMessage: TSInfoMessage,
oldGroupModel: TSGroupModel,
@ -200,6 +204,8 @@ struct CVMessageAction: Equatable {
delegate.cvc_didTapInvalidIdentityKeyErrorMessage(errorMessage)
case .cvc_didTapCorruptedMessage(let errorMessage):
delegate.cvc_didTapCorruptedMessage(errorMessage)
case .cvc_didTapSessionRefreshMessage(let errorMessage):
delegate.cvc_didTapSessionRefreshMessage(errorMessage)
case .cvc_didTapResendGroupUpdate(let errorMessage):
delegate.cvc_didTapResendGroupUpdateForErrorMessage(errorMessage)
case .cvc_didTapShowGroupMigrationLearnMoreActionSheet(let infoMessage,

View File

@ -397,6 +397,8 @@ extension CVComponentSystemMessage {
case .nonBlockingIdentityChange,
.wrongTrustedIdentityKey:
return Theme.iconImage(.safetyNumber16)
case .sessionRefresh:
return Theme.iconImage(.info16)
case .invalidKeyException,
.missingKeyId,
.noSession,
@ -596,6 +598,10 @@ extension CVComponentSystemMessage {
comment: "Label for button to reset a session."),
accessibilityIdentifier: "reset_session",
action: .cvc_didTapCorruptedMessage(errorMessage: message))
case .sessionRefresh:
return Action(title: CommonStrings.learnMore,
accessibilityIdentifier: "learn_more",
action: .cvc_didTapSessionRefreshMessage(errorMessage: message))
case .duplicateMessage,
.invalidVersion:
return nil

View File

@ -4567,6 +4567,35 @@ typedef enum : NSUInteger {
[self presentActionSheet:alert];
}
- (void)cvc_didTapSessionRefreshMessage:(TSErrorMessage *)message
{
[self dismissKeyBoard];
UIImageView *headerImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"chat-session-refresh"]];
UIView *headerView = [UIView new];
[headerView addSubview:headerImageView];
[headerImageView autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:22];
[headerImageView autoPinEdgeToSuperviewEdge:ALEdgeBottom];
[headerImageView autoHCenterInSuperview];
[headerImageView autoSetDimension:ALDimensionWidth toSize:200];
[headerImageView autoSetDimension:ALDimensionHeight toSize:110];
[ContactSupportAlert
presentAlertWithTitle:NSLocalizedString(@"SESSION_REFRESH_ALERT_TITLE", @"Title for the session refresh alert")
message:NSLocalizedString(
@"SESSION_REFRESH_ALERT_MESSAGE", @"Description for the session refresh alert")
emailSupportFilter:@"Signal iOS Session Refresh"
fromViewController:self
additionalActions:@[ [[ActionSheetAction alloc]
initWithTitle:CommonStrings.okayButton
accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, @"okay")
style:ActionSheetActionStyleDefault
handler:^(ActionSheetAction *action) {}] ]
customHeader:headerView
showCancel:NO];
}
- (void)cvc_didTapResendGroupUpdateForErrorMessage:(TSErrorMessage *)message
{
OWSAssertIsOnMainThread();

View File

@ -909,6 +909,9 @@ extension MessageDetailViewController: CVComponentDelegate {
// TODO:
func cvc_didTapCorruptedMessage(_ message: TSErrorMessage) {}
// TODO:
func cvc_didTapSessionRefreshMessage(_ message: TSErrorMessage) {}
// See: resendGroupUpdate
// TODO:
func cvc_didTapResendGroupUpdateForErrorMessage(_ errorMessage: TSErrorMessage) {}

View File

@ -5,15 +5,18 @@
import Foundation
import PromiseKit
public class ContactSupportAlert {
public class func presentAlert(title: String, message: String, emailSupportFilter: String, fromViewController: UIViewController, additionalActions: [ActionSheetAction] = []) {
presentStep1(title: title, message: message, emailSupportFilter: emailSupportFilter, fromViewController: fromViewController, additionalActions: additionalActions)
@objc
public class ContactSupportAlert: NSObject {
@objc
public class func presentAlert(title: String, message: String, emailSupportFilter: String, fromViewController: UIViewController, additionalActions: [ActionSheetAction] = [], customHeader: UIView? = nil, showCancel: Bool = true) {
presentStep1(title: title, message: message, emailSupportFilter: emailSupportFilter, fromViewController: fromViewController, additionalActions: additionalActions, customHeader: customHeader, showCancel: showCancel)
}
// MARK: -
private class func presentStep1(title: String, message: String, emailSupportFilter: String, fromViewController: UIViewController, additionalActions: [ActionSheetAction]) {
private class func presentStep1(title: String, message: String, emailSupportFilter: String, fromViewController: UIViewController, additionalActions: [ActionSheetAction], customHeader: UIView? = nil, showCancel: Bool = true) {
let actionSheet = ActionSheetController(title: title, message: message)
actionSheet.customHeader = customHeader
additionalActions.forEach { actionSheet.addAction($0) }
@ -22,7 +25,7 @@ public class ContactSupportAlert {
self.presentStep2(emailSupportFilter: emailSupportFilter, fromViewController: fromViewController)
}
actionSheet.addAction(proceedAction)
actionSheet.addAction(OWSActionSheets.cancelAction)
if showCancel { actionSheet.addAction(OWSActionSheets.cancelAction) }
fromViewController.present(actionSheet, animated: true)
}

View File

@ -1384,6 +1384,9 @@
/* Shown when signal users safety numbers changed, embeds the user's {{name or phone number}} */
"ERROR_MESSAGE_NON_BLOCKING_IDENTITY_CHANGE_FORMAT" = "Your safety number with %@ has changed.";
/* Text notifying the user that their secure session has been reset */
"ERROR_MESSAGE_SESSION_REFRESH" = "Chat session refreshed";
/* No comment provided by engineer. */
"ERROR_MESSAGE_UNKNOWN_ERROR" = "An unknown error occurred.";
@ -4228,6 +4231,12 @@
/* No comment provided by engineer. */
"SEND_SMS_INVITE_TITLE" = "Would you like to invite the following number to Signal: ";
/* Description for the session refresh alert */
"SESSION_REFRESH_ALERT_MESSAGE" = "Signal uses end-to-end encryption and it may need to refresh your chat session sometimes. This doesnt affect your chats security but you may have missed a message from this contact and you can ask them to resend it.";
/* Title for the session refresh alert */
"SESSION_REFRESH_ALERT_TITLE" = "Chat session refreshed";
/* Navbar title */
"SETTINGS_ABOUT" = "About";

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
//
#import "OWSReadTracking.h"
@ -25,6 +25,7 @@ typedef NS_ENUM(int32_t, TSErrorMessageType) {
TSErrorMessageNonBlockingIdentityChange,
TSErrorMessageUnknownContactBlockOffer,
TSErrorMessageGroupCreationFailed,
TSErrorMessageSessionRefresh
};
@interface ThreadlessErrorMessage : NSObject <OWSPreviewText>
@ -125,6 +126,9 @@ NS_DESIGNATED_INITIALIZER NS_SWIFT_NAME(init(grdbId:uniqueId:receivedAtTimestamp
+ (instancetype)missingSessionWithEnvelope:(SSKProtoEnvelope *)envelope
withTransaction:(SDSAnyWriteTransaction *)transaction;
+ (instancetype)sessionRefreshWithEnvelope:(SSKProtoEnvelope *)envelope
withTransaction:(SDSAnyWriteTransaction *)transaction;
+ (instancetype)nonblockingIdentityChangeInThread:(TSThread *)thread address:(SignalServiceAddress *)address;
@property (nonatomic, readonly) TSErrorMessageType errorType;

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
//
#import "TSErrorMessage.h"
@ -266,6 +266,9 @@ NSUInteger TSErrorMessageSchemaVersion = 2;
case TSErrorMessageGroupCreationFailed:
return NSLocalizedString(@"GROUP_CREATION_FAILED",
@"Message shown in conversation view that indicates there were issues with group creation.");
case TSErrorMessageSessionRefresh:
return NSLocalizedString(
@"ERROR_MESSAGE_SESSION_REFRESH", @"Text notifying the user that their secure session has been reset");
default:
OWSFailDebug(@"failure: unknown error type");
break;
@ -305,6 +308,14 @@ NSUInteger TSErrorMessageSchemaVersion = 2;
failedMessageType:TSErrorMessageNoSession];
}
+ (instancetype)sessionRefreshWithEnvelope:(SSKProtoEnvelope *)envelope
withTransaction:(SDSAnyWriteTransaction *)transaction
{
return [[self alloc] initWithEnvelope:envelope
withTransaction:transaction
failedMessageType:TSErrorMessageSessionRefresh];
}
+ (instancetype)nonblockingIdentityChangeInThread:(TSThread *)thread address:(SignalServiceAddress *)address
{
return [[self alloc] initWithThread:thread

View File

@ -744,30 +744,28 @@ NSError *EnsureDecryptError(NSError *_Nullable error, NSString *fallbackErrorDes
error.localizedDescription);
}];
}
errorMessage = [TSErrorMessage sessionRefreshWithEnvelope:envelope withTransaction:transaction];
} else {
OWSFailDebug(@"Received envelope missing UUID %@.%d", envelope.sourceAddress, envelope.sourceDevice);
errorMessage = [TSErrorMessage corruptedMessageWithEnvelope:envelope withTransaction:transaction];
}
// Log the error appropriately.
if ([exception.name isEqualToString:NoSessionException]) {
OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorNoSession], envelope);
errorMessage = [TSErrorMessage missingSessionWithEnvelope:envelope withTransaction:transaction];
} else if ([exception.name isEqualToString:InvalidKeyException]) {
OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorInvalidKey], envelope);
errorMessage = [TSErrorMessage invalidKeyExceptionWithEnvelope:envelope withTransaction:transaction];
} else if ([exception.name isEqualToString:InvalidKeyIdException]) {
OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorInvalidKeyId], envelope);
errorMessage = [TSErrorMessage invalidKeyExceptionWithEnvelope:envelope withTransaction:transaction];
} else if ([exception.name isEqualToString:InvalidVersionException]) {
OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorInvalidMessageVersion], envelope);
errorMessage = [TSErrorMessage invalidVersionWithEnvelope:envelope withTransaction:transaction];
} else if ([exception.name isEqualToString:UntrustedIdentityKeyException]) {
// Should no longer get here, since we now record the new identity for incoming messages.
OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorUntrustedIdentityKeyException], envelope);
OWSFailDebug(@"Failed to trust identity on incoming message from: %@", envelopeAddress(envelope));
return;
} else {
OWSProdErrorWEnvelope([OWSAnalyticsEvents messageManagerErrorCorruptMessage], envelope);
errorMessage = [TSErrorMessage corruptedMessageWithEnvelope:envelope withTransaction:transaction];
}
OWSAssertDebug(errorMessage);