Add and honor the “CallKit Privacy” setting.

// FREEBIE
This commit is contained in:
Matthew Chen 2017-02-21 23:17:54 -05:00
parent 8104ffa129
commit 065d383c15
7 changed files with 46 additions and 32 deletions

View file

@ -22,7 +22,9 @@ final class CallKitCallManager: NSObject {
// MARK: Actions
func startCall(_ call: SignalCall) {
let handle = CXHandle(type: .phoneNumber, value: call.remotePhoneNumber)
let handle = (Environment.getCurrent().preferences.isCallKitPrivacyEnabled()
? CXHandle(type: .generic, value: call.localId.uuidString)
: CXHandle(type: .phoneNumber, value: call.remotePhoneNumber))
let startCallAction = CXStartCallAction(call: call.localId, handle: handle)
startCallAction.isVideo = call.hasLocalVideo

View file

@ -37,7 +37,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
providerConfiguration.maximumCallsPerCallGroup = 1
providerConfiguration.supportedHandleTypes = [.phoneNumber]
providerConfiguration.supportedHandleTypes = [.phoneNumber, .generic]
if let iconMaskImage = UIImage(named: "IconMask") {
providerConfiguration.iconTemplateImageData = UIImagePNGRepresentation(iconMaskImage)
@ -84,7 +84,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
AssertIsOnMainThread()
Logger.debug("\(self.TAG) \(#function)")
switch (error) {
switch error {
case .timeout(description: _):
provider.reportCall(with: call.localId, endedAt: Date(), reason: CXCallEndedReason.unanswered)
default:
@ -100,8 +100,12 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
// Construct a CXCallUpdate describing the incoming call, including the caller.
let update = CXCallUpdate()
update.remoteHandle = CXHandle(type: .phoneNumber, value: call.remotePhoneNumber)
update.remoteHandle = (Environment.getCurrent().preferences.isCallKitPrivacyEnabled()
? CXHandle(type: .generic, value: call.localId.uuidString)
: CXHandle(type: .phoneNumber, value: call.remotePhoneNumber))
update.hasVideo = call.hasLocalVideo
// Update the name used in the CallKit UI for incoming calls.
update.localizedCallerName = NSLocalizedString("CALLKIT_ANONYMOUS_CONTACT_NAME", comment: "The generic name used for calls if CallKit privacy is enabled")
disableUnsupportedFeatures(callUpdate: update)
// Report the incoming call to the system
@ -192,7 +196,6 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
Logger.debug("\(self.TAG) \(#function)")
let update = CXCallUpdate()
update.remoteHandle = CXHandle(type: .phoneNumber, value: call.remotePhoneNumber)
update.hasVideo = hasLocalVideo
// Update the CallKit UI.
@ -234,6 +237,11 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
_ = self.callService.handleOutgoingCall(call)
action.fulfill()
self.provider.reportOutgoingCall(with: call.localId, startedConnectingAt: nil)
// Update the name used in the CallKit UI for outgoing calls.
let update = CXCallUpdate()
update.localizedCallerName = NSLocalizedString("CALLKIT_ANONYMOUS_CONTACT_NAME", comment: "The generic name used for calls if CallKit privacy is enabled")
provider.reportCall(with: call.localId, updated: update)
}
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {

View file

@ -78,7 +78,7 @@ extension CallUIAdaptee {
// So we use the non-CallKit call UI.
Logger.info("\(TAG) choosing non-callkit adaptee for simulator.")
adaptee = NonCallKitCallUIAdaptee(callService: callService, notificationsAdapter: notificationsAdapter)
} else if #available(iOS 10.0, *), Environment.getCurrent().preferences.isCallKitEnabled() {
} else if #available(iOS 10.0, *) {
Logger.info("\(TAG) choosing callkit adaptee for iOS10+")
adaptee = CallKitCallUIAdaptee(callService: callService, notificationsAdapter: notificationsAdapter)
} else {

View file

@ -68,8 +68,8 @@ extern NSString *const PropertyListPreferencesKeyEnableDebugLog;
#pragma mark Callkit
- (BOOL)isCallKitEnabled;
- (void)setIsCallKitEnabled:(BOOL)flag;
- (BOOL)isCallKitPrivacyEnabled;
- (void)setIsCallKitPrivacyEnabled:(BOOL)flag;
#pragma mark direct call connectivity (non-TURN)

View file

@ -23,6 +23,7 @@ NSString *const PropertyListPreferencesKeyHasRegisteredVoipPush = @"VOIPPushEnab
NSString *const PropertyListPreferencesKeyLastRecordedPushToken = @"LastRecordedPushToken";
NSString *const PropertyListPreferencesKeyLastRecordedVoipToken = @"LastRecordedVoipToken";
NSString *const PropertyListPreferencesKeyCallKitEnabled = @"CallKitEnabled";
NSString *const PropertyListPreferencesKeyCallKitPrivacyEnabled = @"CallKitPrivacyEnabled";
NSString *const PropertyListPreferencesKeyCallsHideIPAddress = @"CallsHideIPAddress";
@implementation PropertyListPreferences
@ -175,15 +176,15 @@ NSString *const PropertyListPreferencesKeyCallsHideIPAddress = @"CallsHideIPAddr
#pragma mark CallKit
- (BOOL)isCallKitEnabled
- (BOOL)isCallKitPrivacyEnabled
{
NSNumber *preference = [self tryGetValueForKey:PropertyListPreferencesKeyCallKitEnabled];
NSNumber *preference = [self tryGetValueForKey:PropertyListPreferencesKeyCallKitPrivacyEnabled];
return preference ? [preference boolValue] : YES;
}
- (void)setIsCallKitEnabled:(BOOL)flag
- (void)setIsCallKitPrivacyEnabled:(BOOL)flag
{
[self setValueForKey:PropertyListPreferencesKeyCallKitEnabled toValue:@(flag)];
[self setValueForKey:PropertyListPreferencesKeyCallKitPrivacyEnabled toValue:@(flag)];
}
#pragma mark direct call connectivity (non-TURN)

View file

@ -18,12 +18,12 @@ NS_ASSUME_NONNULL_BEGIN
@interface AdvancedSettingsTableViewController ()
@property (nonatomic) UITableViewCell *enableCallKitCell;
@property (nonatomic) UITableViewCell *enableCallKitPrivacyCell;
@property (nonatomic) UITableViewCell *enableLogCell;
@property (nonatomic) UITableViewCell *submitLogCell;
@property (nonatomic) UITableViewCell *registerPushCell;
@property (nonatomic) UISwitch *enableCallKitSwitch;
@property (nonatomic) UISwitch *enableCallKitPrivacySwitch;
@property (nonatomic) UISwitch *enableLogSwitch;
@property (nonatomic, readonly) BOOL supportsCallKit;
@ -58,14 +58,14 @@ typedef NS_ENUM(NSInteger, AdvancedSettingsTableViewControllerSection) {
[self useOWSBackButton];
// CallKit opt-out
self.enableCallKitCell = [UITableViewCell new];
self.enableCallKitCell.textLabel.text = NSLocalizedString(@"SETTINGS_ADVANCED_CALLKIT_TITLE", @"Short table cell label");
self.enableCallKitSwitch = [UISwitch new];
[self.enableCallKitSwitch setOn:[[Environment getCurrent].preferences isCallKitEnabled]];
[self.enableCallKitSwitch addTarget:self
action:@selector(didToggleEnableCallKitSwitch:)
forControlEvents:UIControlEventTouchUpInside];
self.enableCallKitCell.accessoryView = self.enableCallKitSwitch;
self.enableCallKitPrivacyCell = [UITableViewCell new];
self.enableCallKitPrivacyCell.textLabel.text = NSLocalizedString(@"SETTINGS_ADVANCED_CALLKIT_PRIVACY_TITLE", @"Label for 'CallKit privacy' preference");
self.enableCallKitPrivacySwitch = [UISwitch new];
[self.enableCallKitPrivacySwitch setOn:![[Environment getCurrent].preferences isCallKitPrivacyEnabled]];
[self.enableCallKitPrivacySwitch addTarget:self
action:@selector(didToggleEnableCallKitPrivacySwitch:)
forControlEvents:UIControlEventTouchUpInside];
self.enableCallKitPrivacyCell.accessoryView = self.enableCallKitPrivacySwitch;
// Enable Log
self.enableLogCell = [[UITableViewCell alloc] init];
@ -99,7 +99,7 @@ typedef NS_ENUM(NSInteger, AdvancedSettingsTableViewControllerSection) {
case AdvancedSettingsTableViewControllerSectionLogging:
return self.enableLogSwitch.isOn ? 2 : 1;
case AdvancedSettingsTableViewControllerSectionCalling:
return self.supportsCallKit ? 2 : 1;
return self.supportsCallKit ? 1 : 0;
case AdvancedSettingsTableViewControllerSectionPushNotifications:
return 1;
default:
@ -128,7 +128,7 @@ typedef NS_ENUM(NSInteger, AdvancedSettingsTableViewControllerSection) {
switch (settingsSection) {
case AdvancedSettingsTableViewControllerSectionCalling:
if ([self supportsCallKit]) {
return NSLocalizedString(@"SETTINGS_SECTION_CALL_KIT_DESCRIPTION", @"Settings table section footer.");
return NSLocalizedString(@"SETTINGS_SECTION_CALL_KIT_PRIVACY_DESCRIPTION", @"Explanation of the 'CallKit Privacy` preference.");
}
default:
return nil;
@ -151,7 +151,7 @@ typedef NS_ENUM(NSInteger, AdvancedSettingsTableViewControllerSection) {
switch (indexPath.row) {
case 0:
OWSAssert(self.supportsCallKit);
return self.enableCallKitCell;
return self.enableCallKitPrivacyCell;
default:
// Unknown cell
OWSAssert(NO);
@ -205,9 +205,9 @@ typedef NS_ENUM(NSInteger, AdvancedSettingsTableViewControllerSection) {
[self.tableView reloadData];
}
- (void)didToggleEnableCallKitSwitch:(UISwitch *)sender {
DDLogInfo(@"%@ user toggled call kit preference: %@", self.tag, (sender.isOn ? @"ON" : @"OFF"));
[[Environment getCurrent].preferences setIsCallKitEnabled:sender.isOn];
- (void)didToggleEnableCallKitPrivacySwitch:(UISwitch *)sender {
DDLogInfo(@"%@ user toggled call kit privacy preference: %@", self.tag, (sender.isOn ? @"ON" : @"OFF"));
[[Environment getCurrent].preferences setIsCallKitPrivacyEnabled:!sender.isOn];
[[Environment getCurrent].callService createCallUIAdapter];
}

View file

@ -85,6 +85,9 @@
/* notification action */
"CALLBACK_BUTTON_TITLE" = "Call back";
/* The generic name used for calls if CallKit privacy is enabled */
"CALLKIT_ANONYMOUS_CONTACT_NAME" = "Signal User";
/* Activity Sheet label */
"COMPARE_SAFETY_NUMBER_ACTION" = "Compare with Clipboard";
@ -757,8 +760,8 @@
/* Navbar title */
"SETTINGS_ABOUT" = "About";
/* Short table cell label */
"SETTINGS_ADVANCED_CALLKIT_TITLE" = "Use CallKit";
/* Label for 'CallKit privacy' preference */
"SETTINGS_ADVANCED_CALLKIT_PRIVACY_TITLE" = "Show Names & Numbers in CallKit";
/* No comment provided by engineer. */
"SETTINGS_ADVANCED_DEBUGLOG" = "Enable Debug Log";
@ -832,8 +835,8 @@
/* No comment provided by engineer. */
"SETTINGS_SCREEN_SECURITY_DETAIL" = "Prevents Signal previews from appearing in the app switcher.";
/* Settings table section footer. */
"SETTINGS_SECTION_CALL_KIT_DESCRIPTION" = "CallKit allows you to answer calls directly from your lockscreen. Be aware that when using CallKit, Apple syncs some call metadata to your iCloud account.";
/* Explanation of the 'CallKit Privacy` preference. */
"SETTINGS_SECTION_CALL_KIT_PRIVACY_DESCRIPTION" = "CallKit allows you to answer calls directly from your lockscreen. If you show the names and phone numbers of incoming callers in CallKit, this information will appear in your phone's call history and will be synced to your iCloud account.";
/* settings topic header for table section */
"SETTINGS_SECTION_TITLE_CALLING" = "Calling";