Prevent outgoing calls started from various places unless have been seen
e.g. from contacts app // FREEBIE
This commit is contained in:
parent
130aa132a0
commit
5b12f4afae
|
@ -137,7 +137,7 @@ CHECKOUT OPTIONS:
|
|||
:commit: 7054e4b13ee5bcd6d524adb6dc9a726e8c466308
|
||||
:git: https://github.com/WhisperSystems/JSQMessagesViewController.git
|
||||
SignalServiceKit:
|
||||
:commit: e10cc0c1803c598a7518b6c8b28195e20f0eb12e
|
||||
:commit: ebd4800e21a1dd3410bfa498f986706c5c71aa4c
|
||||
:git: https://github.com/WhisperSystems/SignalServiceKit.git
|
||||
SocketRocket:
|
||||
:commit: 877ac7438be3ad0b45ef5ca3969574e4b97112bf
|
||||
|
|
|
@ -8,18 +8,24 @@ import Foundation
|
|||
class MarkIdentityAsSeenJob: NSObject {
|
||||
let TAG = "[MarkIdentityAsSeenJob]"
|
||||
|
||||
private let thread: TSThread
|
||||
private let recipientIds: [String]
|
||||
|
||||
public class func run(thread: TSThread) {
|
||||
MarkIdentityAsSeenJob(thread: thread).run()
|
||||
let recipientIds = thread.recipientIdentifiers
|
||||
|
||||
MarkIdentityAsSeenJob(recipientIds: recipientIds).run()
|
||||
}
|
||||
|
||||
init(thread: TSThread) {
|
||||
self.thread = thread
|
||||
public class func run(recipientId: String) {
|
||||
MarkIdentityAsSeenJob(recipientIds: [recipientId]).run()
|
||||
}
|
||||
|
||||
init(recipientIds: [String]) {
|
||||
self.recipientIds = recipientIds
|
||||
}
|
||||
|
||||
public func run() {
|
||||
for recipientId in self.thread.recipientIdentifiers {
|
||||
for recipientId in self.recipientIds {
|
||||
markAsSeenIfNecessary(recipientId: recipientId)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ import Foundation
|
|||
|
||||
static let callStatusFormat = NSLocalizedString("CALL_STATUS_FORMAT", comment: "embeds {{Call Status}} in call screen label. For ongoing calls, {{Call Status}} is a seconds timer like 01:23, otherwise {{Call Status}} is a short text like 'Ringing', 'Busy', or 'Failed Call'")
|
||||
|
||||
static let confirmAndCallButtonTitle = NSLocalizedString("SAFETY_NUMBER_CHANGED_CONFIRM_CALL_ACTION", comment: "alert button text to confirm placing an outgoing call after the recipients Safety Number has changed.")
|
||||
|
||||
// MARK: Notification actions
|
||||
static let callBackButtonTitle = NSLocalizedString("CALLBACK_BUTTON_TITLE", comment: "notification action")
|
||||
static let confirmIdentityAndCallBackButtonTitle = NSLocalizedString("CONFIRM_IDENTITY_AND_CALLBACK_BUTTON_TITLE", comment: "notification action, confirming that it's OK to proceed calling after a caller's Safety Number has changed")
|
||||
|
|
|
@ -67,18 +67,18 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
}
|
||||
|
||||
BOOL didShowSNAlert = [SafetyNumberConfirmationAlert
|
||||
presentAlertIfNecessaryFromViewController:self
|
||||
recipientId:phoneNumber
|
||||
confirmationText:
|
||||
NSLocalizedString(@"SAFETY_NUMBER_CHANGED_CONFIRM_ADD_TO_GROUP_ACTION",
|
||||
@"button title to confirm adding a recipient to a group when their safety "
|
||||
@"number has recently changed")
|
||||
contactsManager:helper.contactsManager
|
||||
completion:^(BOOL didConfirmIdentity) {
|
||||
if (didConfirmIdentity) {
|
||||
[weakSelf addToGroup:phoneNumber];
|
||||
}
|
||||
}];
|
||||
presentAlertIfNecessaryWithRecipientId:phoneNumber
|
||||
confirmationText:
|
||||
NSLocalizedString(@"SAFETY_NUMBER_CHANGED_CONFIRM_ADD_TO_GROUP_ACTION",
|
||||
@"button title to confirm adding a recipient to a group when their safety "
|
||||
@"number has recently changed")
|
||||
contactsManager:helper.contactsManager
|
||||
verifySeen:YES
|
||||
completion:^(BOOL didConfirmIdentity) {
|
||||
if (didConfirmIdentity) {
|
||||
[weakSelf addToGroup:phoneNumber];
|
||||
}
|
||||
}];
|
||||
if (didShowSNAlert) {
|
||||
return;
|
||||
}
|
||||
|
@ -119,18 +119,18 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
}
|
||||
|
||||
BOOL didShowSNAlert = [SafetyNumberConfirmationAlert
|
||||
presentAlertIfNecessaryFromViewController:self
|
||||
recipientId:signalAccount.recipientId
|
||||
confirmationText:
|
||||
NSLocalizedString(@"SAFETY_NUMBER_CHANGED_CONFIRM_ADD_TO_GROUP_ACTION",
|
||||
@"button title to confirm adding a recipient to a group when their safety "
|
||||
@"number has recently changed")
|
||||
contactsManager:helper.contactsManager
|
||||
completion:^(BOOL didConfirmIdentity) {
|
||||
if (didConfirmIdentity) {
|
||||
[weakSelf addToGroup:signalAccount.recipientId];
|
||||
}
|
||||
}];
|
||||
presentAlertIfNecessaryWithRecipientId:signalAccount.recipientId
|
||||
confirmationText:
|
||||
NSLocalizedString(@"SAFETY_NUMBER_CHANGED_CONFIRM_ADD_TO_GROUP_ACTION",
|
||||
@"button title to confirm adding a recipient to a group when their safety "
|
||||
@"number has recently changed")
|
||||
contactsManager:helper.contactsManager
|
||||
verifySeen:YES
|
||||
completion:^(BOOL didConfirmIdentity) {
|
||||
if (didConfirmIdentity) {
|
||||
[weakSelf addToGroup:signalAccount.recipientId];
|
||||
}
|
||||
}];
|
||||
if (didShowSNAlert) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1638,11 +1638,11 @@ typedef enum : NSUInteger {
|
|||
completion:
|
||||
(void (^)(BOOL didConfirmedIdentity))completionHandler
|
||||
{
|
||||
return [SafetyNumberConfirmationAlert presentAlertIfNecessaryFromViewController:self
|
||||
recipientIds:self.thread.recipientIdentifiers
|
||||
confirmationText:confirmationText
|
||||
contactsManager:self.contactsManager
|
||||
completion:completionHandler];
|
||||
return [SafetyNumberConfirmationAlert presentAlertIfNecessaryWithRecipientIds:self.thread.recipientIdentifiers
|
||||
confirmationText:confirmationText
|
||||
contactsManager:self.contactsManager
|
||||
verifySeen:NO
|
||||
completion:completionHandler];
|
||||
}
|
||||
|
||||
- (void)showFingerprintWithTheirIdentityKey:(NSData *)theirIdentityKey theirSignalId:(NSString *)theirSignalId
|
||||
|
@ -1694,15 +1694,13 @@ typedef enum : NSUInteger {
|
|||
return;
|
||||
}
|
||||
|
||||
BOOL didShowSNAlert = [self showSafetyNumberConfirmationIfNecessaryWithConfirmationText:
|
||||
NSLocalizedString(@"SAFETY_NUMBER_CHANGED_CONFIRM_CALL_ACTION",
|
||||
@"button title to confirm calling a recipient whose safety "
|
||||
@"number recently changed")
|
||||
completion:^(BOOL didConfirmIdentity) {
|
||||
if (didConfirmIdentity) {
|
||||
[weakSelf callAction:sender];
|
||||
}
|
||||
}];
|
||||
BOOL didShowSNAlert =
|
||||
[self showSafetyNumberConfirmationIfNecessaryWithConfirmationText:[CallStrings confirmAndCallButtonTitle]
|
||||
completion:^(BOOL didConfirmIdentity) {
|
||||
if (didConfirmIdentity) {
|
||||
[weakSelf callAction:sender];
|
||||
}
|
||||
}];
|
||||
if (didShowSNAlert) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -252,21 +252,21 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68;
|
|||
} else {
|
||||
|
||||
BOOL didShowSNAlert = [SafetyNumberConfirmationAlert
|
||||
presentAlertIfNecessaryFromViewController:self
|
||||
recipientId:recipientId
|
||||
confirmationText:NSLocalizedString(
|
||||
@"SAFETY_NUMBER_CHANGED_CONFIRM_"
|
||||
@"ADD_TO_GROUP_ACTION",
|
||||
@"button title to confirm adding "
|
||||
@"a recipient to a group when "
|
||||
@"their safety "
|
||||
@"number has recently changed")
|
||||
contactsManager:contactsViewHelper.contactsManager
|
||||
completion:^(BOOL didConfirmIdentity) {
|
||||
if (didConfirmIdentity) {
|
||||
[weakSelf addRecipientId:recipientId];
|
||||
}
|
||||
}];
|
||||
presentAlertIfNecessaryWithRecipientId:recipientId
|
||||
confirmationText:NSLocalizedString(
|
||||
@"SAFETY_NUMBER_CHANGED_CONFIRM_"
|
||||
@"ADD_TO_GROUP_ACTION",
|
||||
@"button title to confirm adding "
|
||||
@"a recipient to a group when "
|
||||
@"their safety "
|
||||
@"number has recently changed")
|
||||
contactsManager:contactsViewHelper.contactsManager
|
||||
verifySeen:YES
|
||||
completion:^(BOOL didConfirmIdentity) {
|
||||
if (didConfirmIdentity) {
|
||||
[weakSelf addRecipientId:recipientId];
|
||||
}
|
||||
}];
|
||||
if (didShowSNAlert) {
|
||||
return;
|
||||
}
|
||||
|
@ -342,21 +342,21 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68;
|
|||
}];
|
||||
} else {
|
||||
BOOL didShowSNAlert = [SafetyNumberConfirmationAlert
|
||||
presentAlertIfNecessaryFromViewController:self
|
||||
recipientId:signalAccount.recipientId
|
||||
confirmationText:NSLocalizedString(
|
||||
@"SAFETY_NUMBER_CHANGED_CONFIRM_"
|
||||
@"ADD_TO_GROUP_ACTION",
|
||||
@"button title to confirm adding "
|
||||
@"a recipient to a group when "
|
||||
@"their safety "
|
||||
@"number has recently changed")
|
||||
contactsManager:contactsViewHelper.contactsManager
|
||||
completion:^(BOOL didConfirmIdentity) {
|
||||
if (didConfirmIdentity) {
|
||||
[weakSelf addRecipientId:recipientId];
|
||||
}
|
||||
}];
|
||||
presentAlertIfNecessaryWithRecipientId:signalAccount.recipientId
|
||||
confirmationText:NSLocalizedString(
|
||||
@"SAFETY_NUMBER_CHANGED_CONFIRM_"
|
||||
@"ADD_TO_GROUP_ACTION",
|
||||
@"button title to confirm adding "
|
||||
@"a recipient to a group when "
|
||||
@"their safety "
|
||||
@"number has recently changed")
|
||||
contactsManager:contactsViewHelper.contactsManager
|
||||
verifySeen:YES
|
||||
completion:^(BOOL didConfirmIdentity) {
|
||||
if (didConfirmIdentity) {
|
||||
[weakSelf addRecipientId:recipientId];
|
||||
}
|
||||
}];
|
||||
if (didShowSNAlert) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -16,14 +16,14 @@ class SafetyNumberConfirmationAlert: NSObject {
|
|||
self.storageManager = TSStorageManager.shared()
|
||||
}
|
||||
|
||||
public class func presentAlertIfNecessary(fromViewController: UIViewController, recipientId: String, confirmationText: String, contactsManager: OWSContactsManager, completion: @escaping (Bool) -> Void) -> Bool {
|
||||
return self.presentAlertIfNecessary(fromViewController: fromViewController, recipientIds: [recipientId], confirmationText: confirmationText, contactsManager: contactsManager, completion: completion)
|
||||
public class func presentAlertIfNecessary(recipientId: String, confirmationText: String, contactsManager: OWSContactsManager, verifySeen: Bool, completion: @escaping (Bool) -> Void) -> Bool {
|
||||
return self.presentAlertIfNecessary(recipientIds: [recipientId], confirmationText: confirmationText, contactsManager: contactsManager, verifySeen: verifySeen, completion: completion)
|
||||
}
|
||||
|
||||
public class func presentAlertIfNecessary(fromViewController: UIViewController, recipientIds: [String], confirmationText: String, contactsManager: OWSContactsManager, completion: @escaping (Bool) -> Void) -> Bool {
|
||||
return SafetyNumberConfirmationAlert(contactsManager: contactsManager).presentIfNecessary(fromViewController: fromViewController,
|
||||
recipientIds: recipientIds,
|
||||
public class func presentAlertIfNecessary(recipientIds: [String], confirmationText: String, contactsManager: OWSContactsManager, verifySeen: Bool, completion: @escaping (Bool) -> Void) -> Bool {
|
||||
return SafetyNumberConfirmationAlert(contactsManager: contactsManager).presentIfNecessary(recipientIds: recipientIds,
|
||||
confirmationText: confirmationText,
|
||||
verifySeen: verifySeen,
|
||||
completion: completion)
|
||||
}
|
||||
|
||||
|
@ -33,18 +33,25 @@ class SafetyNumberConfirmationAlert: NSObject {
|
|||
* @returns true if an alert was shown
|
||||
* false if there were no unconfirmed identities
|
||||
*/
|
||||
public func presentIfNecessary(fromViewController: UIViewController, recipientIds: [String], confirmationText: String, completion: @escaping (Bool) -> Void) -> Bool {
|
||||
public func presentIfNecessary(recipientIds: [String], confirmationText: String, verifySeen: Bool, completion: @escaping (Bool) -> Void) -> Bool {
|
||||
|
||||
guard let unconfirmedIdentity = self.unconfirmedIdentityThatShouldBlockSending(recipientIds: recipientIds) else {
|
||||
let unconfirmedIdentity = unconfirmedIdentities(recipientIds: recipientIds).first
|
||||
|
||||
var unseenIdentity: OWSRecipientIdentity?
|
||||
if verifySeen {
|
||||
unseenIdentity = unseenIdentities(recipientIds: recipientIds).first
|
||||
}
|
||||
|
||||
guard let untrustedIdentity = [unseenIdentity, unconfirmedIdentity].flatMap({ $0 }).first else {
|
||||
// No identities to confirm, no alert to present.
|
||||
return false
|
||||
}
|
||||
|
||||
let displayName: String = {
|
||||
if let signalAccount = contactsManager.signalAccountMap[unconfirmedIdentity.recipientId] {
|
||||
if let signalAccount = contactsManager.signalAccountMap[untrustedIdentity.recipientId] {
|
||||
return contactsManager.displayName(for: signalAccount)
|
||||
} else {
|
||||
return contactsManager.displayName(forPhoneIdentifier: unconfirmedIdentity.recipientId)
|
||||
return contactsManager.displayName(forPhoneIdentifier: untrustedIdentity.recipientId)
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -59,12 +66,14 @@ class SafetyNumberConfirmationAlert: NSObject {
|
|||
let actionSheetController = UIAlertController(title: title, message:body, preferredStyle: .actionSheet)
|
||||
|
||||
let confirmAction = UIAlertAction(title: confirmationText, style: .default) { _ in
|
||||
Logger.info("\(self.TAG) Confirmed identity: \(unconfirmedIdentity)")
|
||||
Logger.info("\(self.TAG) Confirmed identity: \(untrustedIdentity)")
|
||||
|
||||
OWSDispatch.sessionStoreQueue().async {
|
||||
self.storageManager.saveRemoteIdentity(unconfirmedIdentity.identityKey,
|
||||
recipientId: unconfirmedIdentity.recipientId,
|
||||
self.storageManager.saveRemoteIdentity(untrustedIdentity.identityKey,
|
||||
recipientId: untrustedIdentity.recipientId,
|
||||
approvedForBlockingUse: true,
|
||||
approvedForNonBlockingUse: true)
|
||||
MarkIdentityAsSeenJob.run(recipientId: untrustedIdentity.recipientId)
|
||||
DispatchQueue.main.async {
|
||||
completion(true)
|
||||
}
|
||||
|
@ -73,11 +82,10 @@ class SafetyNumberConfirmationAlert: NSObject {
|
|||
actionSheetController.addAction(confirmAction)
|
||||
|
||||
let showSafetyNumberAction = UIAlertAction(title: NSLocalizedString("VERIFY_PRIVACY", comment: "Action sheet item"), style: .default) { _ in
|
||||
Logger.info("\(self.TAG) Opted to show Safety Number for identity: \(unconfirmedIdentity)")
|
||||
Logger.info("\(self.TAG) Opted to show Safety Number for identity: \(untrustedIdentity)")
|
||||
|
||||
self.presentSafetyNumberViewController(fromViewController: fromViewController,
|
||||
theirIdentityKey: unconfirmedIdentity.identityKey,
|
||||
theirRecipientId: unconfirmedIdentity.recipientId,
|
||||
self.presentSafetyNumberViewController(theirIdentityKey: untrustedIdentity.identityKey,
|
||||
theirRecipientId: untrustedIdentity.recipientId,
|
||||
theirDisplayName: displayName,
|
||||
completion: { completion(false) })
|
||||
|
||||
|
@ -87,11 +95,11 @@ class SafetyNumberConfirmationAlert: NSObject {
|
|||
let dismissAction = UIAlertAction(title: NSLocalizedString("TXT_CANCEL_TITLE", comment: "generic cancel text"), style: .cancel)
|
||||
actionSheetController.addAction(dismissAction)
|
||||
|
||||
fromViewController.present(actionSheetController, animated: true)
|
||||
UIApplication.shared.frontmostViewController?.present(actionSheetController, animated: true)
|
||||
return true
|
||||
}
|
||||
|
||||
public func presentSafetyNumberViewController(fromViewController: UIViewController, theirIdentityKey: Data, theirRecipientId: String, theirDisplayName: String, completion: (() -> Void)? = nil) {
|
||||
public func presentSafetyNumberViewController(theirIdentityKey: Data, theirRecipientId: String, theirDisplayName: String, completion: (() -> Void)? = nil) {
|
||||
let fingerprintViewController = UIStoryboard.instantiateFingerprintViewController()
|
||||
|
||||
let fingerprintBuilder = OWSFingerprintBuilder(storageManager: self.storageManager, contactsManager: self.contactsManager)
|
||||
|
@ -99,21 +107,19 @@ class SafetyNumberConfirmationAlert: NSObject {
|
|||
|
||||
fingerprintViewController.configure(fingerprint: fingerprint, contactName: theirDisplayName)
|
||||
|
||||
fromViewController.present(fingerprintViewController, animated: true, completion: completion)
|
||||
UIApplication.shared.frontmostViewController?.present(fingerprintViewController, animated: true, completion: completion)
|
||||
}
|
||||
|
||||
private func unconfirmedIdentitiesThatShouldBlockSending(recipientIds: [String]) -> [OWSRecipientIdentity] {
|
||||
private func unconfirmedIdentities(recipientIds: [String]) -> [OWSRecipientIdentity] {
|
||||
return recipientIds.flatMap {
|
||||
return self.storageManager.unconfirmedIdentityThatShouldBlockSending(forRecipientId: $0)
|
||||
self.storageManager.unconfirmedIdentityThatShouldBlockSending(forRecipientId: $0)
|
||||
}
|
||||
}
|
||||
|
||||
private func unconfirmedIdentityThatShouldBlockSending(recipientIds: [String]) -> OWSRecipientIdentity? {
|
||||
return unconfirmedIdentitiesThatShouldBlockSending(recipientIds: recipientIds).first
|
||||
}
|
||||
|
||||
private func shouldShow(recipientIds: [String]) -> Bool {
|
||||
return !unconfirmedIdentitiesThatShouldBlockSending(recipientIds: recipientIds).isEmpty
|
||||
private func unseenIdentities(recipientIds: [String]) -> [OWSRecipientIdentity] {
|
||||
return recipientIds.flatMap {
|
||||
self.storageManager.unseenIdentityChange(forRecipientId: $0)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -470,7 +470,7 @@ protocol CallServiceObserver: class {
|
|||
|
||||
let newCall = SignalCall.incomingCall(localId: UUID(), remotePhoneNumber: thread.contactIdentifier(), signalingId: callId)
|
||||
|
||||
guard !self.storageManager.hasUnseenIdentityChange(forRecipientId: thread.contactIdentifier()) else {
|
||||
guard self.storageManager.unseenIdentityChange(forRecipientId: thread.contactIdentifier()) == nil else {
|
||||
let callerName = self.contactsManager.displayName(forPhoneIdentifier: thread.contactIdentifier())
|
||||
self.notificationsAdapter.presentRejectedCallWithUnseenIdentityChange(newCall, callerName: callerName)
|
||||
return
|
||||
|
|
|
@ -46,7 +46,17 @@ import Foundation
|
|||
return false
|
||||
}
|
||||
|
||||
// TODO possible to get here when. e.g. dialing from contacts/recent calls. Should verify seen latest SN.
|
||||
let showedAlert = SafetyNumberConfirmationAlert.presentAlertIfNecessary(recipientId: recipientId,
|
||||
confirmationText: CallStrings.confirmAndCallButtonTitle,
|
||||
contactsManager: self.contactsManager,
|
||||
verifySeen: true) { didConfirmIdentity in
|
||||
if didConfirmIdentity {
|
||||
_ = self.initiateCall(recipientId: recipientId)
|
||||
}
|
||||
}
|
||||
guard !showedAlert else {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check for microphone permissions
|
||||
// Alternative way without prompting for permissions:
|
||||
|
|
Loading…
Reference in New Issue