- Use of new Keychain Access attribute
- Error management (notifying the user) when opening app without
required push and microphone permission
- Enforcing APNID are sent to server, retry later if not able to reach
server
This commit is contained in:
Frederic Jacobs 2014-08-01 01:53:58 -04:00
parent 3113665f08
commit 60fb869baa
31 changed files with 287 additions and 100 deletions

View File

@ -2,8 +2,9 @@ platform :ios, '7.0'
link_with ["Signal", "SignalTests"]
pod 'UICKeyChainStore', :podspec => 'Podspecs/UICKeyChainStore.podspec'
pod 'UICKeyChainStore', :podspec => 'Podspecs/UICKeyChainStore.podspec'
pod 'OpenSSL', '~> 1.0.108'
pod 'MMDrawerController', '~> 0.5.0'
pod 'libPhoneNumber-iOS', '~> 0.7'
pod 'PastelogKit', '~> 1.0'
pod 'PastelogKit', '~> 1.0'
pod 'AFNetworking', '~> 2.3.1'

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "UICKeyChainStore"
s.version = "1.0.6"
s.version = "1.0.7"
s.summary = "UICKeyChainStore is a simple wrapper for Keychain on iOS and OS X. Makes using Keychain APIs as easy as NSUserDefaults."
s.homepage = "https://github.com/kishikawakatsumi/UICKeyChainStore"
s.social_media_url = "https://twitter.com/k_katsumi"

View File

@ -378,10 +378,12 @@
A1C32D5117A06544000A904E /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1C32D4D17A0652C000A904E /* AddressBook.framework */; };
AA0C8E498E2046B0B81EEE6E /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8313AE91B4954215858A5662 /* libPods.a */; };
B60C16651988999D00E97A6C /* VersionMigrations.m in Sources */ = {isa = PBXBuildFile; fileRef = B60C16641988999D00E97A6C /* VersionMigrations.m */; };
B67ADDC41989FF8700E1A773 /* CallServerRequestsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B67ADDC31989FF8700E1A773 /* CallServerRequestsManager.m */; };
B67EBF5D19194AC60084CCFD /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = B67EBF5C19194AC60084CCFD /* Settings.bundle */; };
B69CD25119773E79005CE69A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B69CD25019773E79005CE69A /* XCTest.framework */; };
B6B1013C196D213F007E3930 /* SGNKeychainUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B1013B196D213F007E3930 /* SGNKeychainUtil.m */; };
B6B6C3C71919440C00C0B76B /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = B6B6C3C51919440C00C0B76B /* Localizable.strings */; };
B6B9ECFC198B31BA00C620D3 /* PushManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B9ECFB198B31BA00C620D3 /* PushManager.m */; };
B90418E6183E9DD40038554A /* DateUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B90418E5183E9DD40038554A /* DateUtil.m */; };
B90418E7183E9DD40038554A /* DateUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B90418E5183E9DD40038554A /* DateUtil.m */; };
B942EB0E183A9633000887BB /* SearchBarTitleView.m in Sources */ = {isa = PBXBuildFile; fileRef = B942EB0D183A9633000887BB /* SearchBarTitleView.m */; };
@ -1071,6 +1073,8 @@
B60C16631988999D00E97A6C /* VersionMigrations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VersionMigrations.h; sourceTree = "<group>"; };
B60C16641988999D00E97A6C /* VersionMigrations.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VersionMigrations.m; sourceTree = "<group>"; };
B657DDC91911A40500F45B0C /* Signal.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Signal.entitlements; sourceTree = "<group>"; };
B67ADDC21989FF8700E1A773 /* CallServerRequestsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallServerRequestsManager.h; sourceTree = "<group>"; };
B67ADDC31989FF8700E1A773 /* CallServerRequestsManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CallServerRequestsManager.m; sourceTree = "<group>"; };
B67EBF5C19194AC60084CCFD /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = Settings.bundle; path = SettingsBundle/Settings.bundle; sourceTree = SOURCE_ROOT; };
B69CD25019773E79005CE69A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
B6B1013A196D213F007E3930 /* SGNKeychainUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGNKeychainUtil.h; sourceTree = "<group>"; };
@ -1083,6 +1087,8 @@
B6B6C3CC1919454200C0B76B /* ro-RO */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ro-RO"; path = "ro-RO.lproj/Localizable.strings"; sourceTree = "<group>"; };
B6B6C3CD1919455400C0B76B /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
B6B6C3CE1919456C00C0B76B /* sv-SE */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "sv-SE"; path = "sv-SE.lproj/Localizable.strings"; sourceTree = "<group>"; };
B6B9ECFA198B31BA00C620D3 /* PushManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PushManager.h; sourceTree = "<group>"; };
B6B9ECFB198B31BA00C620D3 /* PushManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PushManager.m; sourceTree = "<group>"; };
B90418E4183E9DD40038554A /* DateUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DateUtil.h; sourceTree = "<group>"; };
B90418E5183E9DD40038554A /* DateUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DateUtil.m; sourceTree = "<group>"; };
B942EB0C183A9633000887BB /* SearchBarTitleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SearchBarTitleView.h; sourceTree = "<group>"; };
@ -1676,6 +1682,8 @@
76EB043C18170B33006006FC /* rtp */,
76EB047718170B33006006FC /* tcp */,
76EB048518170B33006006FC /* udp */,
B6B9ECFA198B31BA00C620D3 /* PushManager.h */,
B6B9ECFB198B31BA00C620D3 /* PushManager.m */,
);
path = network;
sourceTree = "<group>";
@ -1705,6 +1713,8 @@
76EB042818170B33006006FC /* http */ = {
isa = PBXGroup;
children = (
B67ADDC21989FF8700E1A773 /* CallServerRequestsManager.h */,
B67ADDC31989FF8700E1A773 /* CallServerRequestsManager.m */,
76EB042918170B33006006FC /* HttpManager.h */,
76EB042A18170B33006006FC /* HttpManager.m */,
76EB042B18170B33006006FC /* HttpRequest.h */,
@ -2985,10 +2995,12 @@
70B80119190C55660042E3F0 /* TextFormat.m in Sources */,
E197B61818BBEC1A00F073E5 /* RemoteIOAudio.m in Sources */,
70B8011C190C55660042E3F0 /* Utilities.m in Sources */,
B67ADDC41989FF8700E1A773 /* CallServerRequestsManager.m in Sources */,
76EB059418170B33006006FC /* HttpManager.m in Sources */,
76EB05EC18170B33006006FC /* CallState.m in Sources */,
76EB05D218170B33006006FC /* ZrtpInitiator.m in Sources */,
76EB05E018170B33006006FC /* NetworkStream.m in Sources */,
B6B9ECFC198B31BA00C620D3 /* PushManager.m in Sources */,
76EB05D618170B33006006FC /* ZrtpResponder.m in Sources */,
70B8010E190C55660042E3F0 /* CodedInputStream.m in Sources */,
7095B7B018F46D35002C66E2 /* PhoneNumberUtil.m in Sources */,
@ -3511,7 +3523,7 @@
LLVM_LTO = NO;
OTHER_LDFLAGS = "$(inherited)";
PRODUCT_NAME = Signal;
PROVISIONING_PROFILE = "036480DA-A21D-4CC6-BF48-98E8AE1EE981";
PROVISIONING_PROFILE = "A4026C2D-D5F0-40C5-B1B4-5EA8E8A1876B";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = 1;
TEST_AFTER_BUILD = YES;
@ -3747,7 +3759,7 @@
LLVM_LTO = NO;
OTHER_LDFLAGS = "$(inherited)";
PRODUCT_NAME = Signal;
PROVISIONING_PROFILE = "036480DA-A21D-4CC6-BF48-98E8AE1EE981";
PROVISIONING_PROFILE = "A4026C2D-D5F0-40C5-B1B4-5EA8E8A1876B";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = 1;
TEST_AFTER_BUILD = YES;
@ -3795,7 +3807,7 @@
LLVM_LTO = NO;
OTHER_LDFLAGS = "$(inherited)";
PRODUCT_NAME = Signal;
PROVISIONING_PROFILE = "036480DA-A21D-4CC6-BF48-98E8AE1EE981";
PROVISIONING_PROFILE = "A4026C2D-D5F0-40C5-B1B4-5EA8E8A1876B";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = 1;
TEST_AFTER_BUILD = YES;

View File

@ -47,9 +47,8 @@
</array>
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
<string>fetch</string>
<string>audio</string>
<string>remote-notification</string>
<string>voip</string>
</array>
<key>UIRequiredDeviceCapabilities</key>

View File

@ -8,6 +8,7 @@
#import "LeftSideMenuViewController.h"
#import "MMDrawerController.h"
#import "NotificationTracker.h"
#import "PushManager.h"
#import "PriorityQueue.h"
#import "RecentCallManager.h"
#import "Release.h"
@ -16,6 +17,7 @@
#import "Util.h"
#import <UICKeyChainStore/UICKeyChainStore.h>
#import "Environment.h"
#import "CallServerRequestsManager.h"
#define kSignalVersionKey @"SignalUpdateVersionKey"
@ -31,9 +33,7 @@
@end
@implementation AppDelegate {
FutureSource* futureApnIdSource;
}
@implementation AppDelegate
#pragma mark Detect updates - perform migrations
@ -44,13 +44,11 @@
if (!previousVersion) {
DDLogError(@"No previous version found. Possibly first launch since install.");
[Environment setCurrent:[Release releaseEnvironmentWithLogging:nil]];
[Environment resetAppData]; // We clean previous keychain entries in case their are some entries remaining.
} else if ([currentVersion compare:previousVersion options:NSNumericSearch] == NSOrderedDescending){
// Application was updated, let's see if we have a migration scheme for it.
if ([previousVersion isEqualToString:@"1.0.2"]) {
// Migrate from custom preferences to NSUserDefaults
}
}
@ -66,31 +64,32 @@
- (void)protectPreferenceFiles{
// We have two kind of data to deal with for now, preference files (/Library/Preferences), logs (/Library/Caches) and pr
NSMutableArray *pathsToExclude = [NSMutableArray array];
NSString *path = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSLog(@"PATH: %@", path);
[pathsToExclude addObject:[[[NSHomeDirectory() stringByAppendingString:@"/Library/Preferences/"] stringByAppendingString:[[NSBundle mainBundle] bundleIdentifier]] stringByAppendingString:@".plist"]];
NSString *path2 = [NSHomeDirectory() stringByAppendingString:@"/Documents"];
NSArray *directoryEnum = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path2 error:nil];
NSLog(@"%@",directoryEnum);
NSLog(@"%@ vs %@", NSHomeDirectory(), [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]);
NSString *preferencesPath = [NSHomeDirectory() stringByAppendingString:@"/Library/Preferences"];
NSString *userDefaultsString = [NSString stringWithFormat:@"%@/%@.plist", preferencesPath,[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"]];
NSURL *userDefaultsURL = [NSURL fileURLWithPath:userDefaultsString];
NSError *error;
[userDefaultsURL setResourceValue: [NSNumber numberWithBool: YES]
forKey: NSURLIsExcludedFromBackupKey error: &error];
NSString *logPath = [NSHomeDirectory() stringByAppendingString:@"/Library/Caches/Logs/"];
NSArray *logsFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:logPath error:&error];
for (NSUInteger i = 0; i < [logsFiles count]; i++) {
[pathsToExclude addObject:[logPath stringByAppendingString:[logsFiles objectAtIndex:i]]];
}
for (NSUInteger i = 0; i < [pathsToExclude count]; i++) {
[[NSURL fileURLWithPath:[pathsToExclude objectAtIndex:i]] setResourceValue: [NSNumber numberWithBool: YES]
forKey: NSURLIsExcludedFromBackupKey error: &error];
}
if (error) {
NSLog(@"Error: %@", error.description);
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:NSLocalizedString(@"WARNING", @"") message:NSLocalizedString(@"DISABLING_BACKUP_FAILED", @"") delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", @"") otherButtonTitles:nil, nil];
[alert show];
return;
}
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
@ -107,10 +106,6 @@
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.notificationTracker = [NotificationTracker notificationTracker];
// start register for apn id
futureApnIdSource = [FutureSource new];
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeSound| UIRemoteNotificationTypeAlert)];
CategorizingLogger* logger = [CategorizingLogger categorizingLogger];
[logger addLoggingCallback:^(NSString *category, id details, NSUInteger index) {}];
[Environment setCurrent:[Release releaseEnvironmentWithLogging:logger]];
@ -119,8 +114,6 @@
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
LeftSideMenuViewController *leftSideMenuViewController = [LeftSideMenuViewController new];
leftSideMenuViewController.centerTabBarViewController.inboxFeedViewController.apnId = futureApnIdSource;
leftSideMenuViewController.centerTabBarViewController.settingsViewController.apnId = futureApnIdSource;
self.drawerController = [[MMDrawerController alloc] initWithCenterViewController:leftSideMenuViewController.centerTabBarViewController leftDrawerViewController:leftSideMenuViewController];
self.window.rootViewController = _drawerController;
@ -135,7 +128,6 @@
[[[Environment phoneManager] currentCallObservable] watchLatestValue:^(CallState* latestCall) {
if (latestCall == nil){
DDLogError(@"Latest Call is nil.");
return;
}
@ -143,17 +135,18 @@
andOptionallyKnownContact:[latestCall potentiallySpecifiedContact]];
[_drawerController.centerViewController presentViewController:callViewController animated:YES completion:nil];
} onThread:[NSThread mainThread] untilCancelled:nil];
return YES;
}
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
DDLogDebug(@"Device registered for push");
[futureApnIdSource trySetResult:deviceToken];
[[PushManager sharedManager] registerForPushWithToken:deviceToken];
}
- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error {
[[PushManager sharedManager]verifyPushActivated];
DDLogError(@"Failed to register for push notifications: %@", error);
[futureApnIdSource trySetFailure:error];
}
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
@ -181,6 +174,11 @@
-(void) applicationDidBecomeActive:(UIApplication *)application {
[[AppAudioManager sharedInstance] awake];
application.applicationIconBadgeNumber = 0;
if ([Environment isRegistered]) {
[[PushManager sharedManager] verifyPushActivated];
[[AppAudioManager sharedInstance] requestRequiredPermissionsIfNeeded];
}
}
@end

View File

@ -159,7 +159,10 @@ AppAudioManager* sharedAppAudioManager;
-(void) requestRequiredPermissionsIfNeeded {
[[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
//todo: take action?
if (!granted) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"ACTION_REQUIRED_TITLE", @"") message:NSLocalizedString(@"AUDIO_PERMISSION_MESSAGE", @"") delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", @"") otherButtonTitles:nil, nil];
[alertView show];
}
}];
}

View File

@ -17,7 +17,7 @@
NSTimeInterval audioDurationPerPacket = (NSTimeInterval)(AUDIO_FRAMES_PER_PACKET*[SpeexCodec frameSizeInSamples])
/ SAMPLE_RATE;
double initialDesiredBufferDepth = [[[Environment getCurrent]preferences] getCachedOrDefaultDesiredBufferDepth];
double initialDesiredBufferDepth = [[Environment preferences] getCachedOrDefaultDesiredBufferDepth];
DropoutTracker* dropoutTracker = [DropoutTracker dropoutTrackerWithAudioDurationPerPacket:audioDurationPerPacket];
@ -59,7 +59,7 @@
}
-(void) terminate {
[[[Environment getCurrent]preferences] setCachedDesiredBufferDepth:[decayingDesiredBufferDepth currentEstimate]];
[[Environment preferences] setCachedDesiredBufferDepth:[decayingDesiredBufferDepth currentEstimate]];
}
@end

View File

@ -51,7 +51,7 @@ typedef BOOL (^SearchTermConditionalBlock)(RecentCall*, NSUInteger, BOOL*);
require(phoneManager != nil);
[[phoneManager currentCallObservable] watchLatestValue:^(CallState* latestCall) {
if (latestCall != nil && [[[Environment getCurrent] preferences] getHistoryLogEnabled]) {
if (latestCall != nil && [[Environment preferences] getHistoryLogEnabled]) {
[self addCall:latestCall];
}
} onThread:[NSThread mainThread] untilCancelled:untilCancelledToken];
@ -101,7 +101,7 @@ typedef BOOL (^SearchTermConditionalBlock)(RecentCall*, NSUInteger, BOOL*);
- (void)addRecentCall:(RecentCall *)recentCall {
[_allRecents insertObject:recentCall atIndex:0];
[[[Environment getCurrent] preferences] setFreshInstallTutorialsEnabled:NO];
[[Environment preferences] setFreshInstallTutorialsEnabled:NO];
[observableRecentsController updateValue:[_allRecents copy]];
[self saveContactsToDefaults];
}

View File

@ -74,7 +74,7 @@ static NSString *const DEFAULTS_KEY_DATE = @"DefaultsKeyDate";
}
- (UIImage *)image {
if ([[[Environment getCurrent] preferences] getContactImagesEnabled]) {
if ([[Environment preferences] getContactImagesEnabled]) {
return image;
} else {
return nil;

View File

@ -71,7 +71,7 @@ andCurrentRegionCodeForPhoneNumbers:(NSString*)currentRegionCodeForPhoneNumbers
+(bool) hasEnabledTestingOrLegacyOption:(NSString*)flag;
+(PhoneManager*) phoneManager;
-(PropertyListPreferences*)preferences;
+(PropertyListPreferences*)preferences;
+(BOOL)isRegistered;
+(void)setRegistered:(BOOL)status;

View File

@ -159,14 +159,13 @@ phoneDirectoryManager;
[[NSUserDefaults standardUserDefaults] setObject:status?@YES:@NO forKey:isRegisteredUserDefaultString];
}
-(PropertyListPreferences*)preferences{
+(PropertyListPreferences*)preferences{
return [[PropertyListPreferences alloc]init];
}
+(void)resetAppData{
[SGNKeychainUtil wipeKeychain];
[NSUserDefaults resetStandardUserDefaults];
[[[Environment getCurrent] preferences] clear];
[[Environment preferences] clear];
}
@end

View File

@ -22,5 +22,7 @@
-(void) setContactImagesEnabled:(BOOL)enabled;
-(void) setAutocorrectEnabled:(BOOL)enabled;
-(void) setHistoryLogEnabled:(BOOL)enabled;
-(BOOL) encounteredRevokedPushPermission;
-(void) setRevokedPushPermission:(BOOL)revoked;
@end

View File

@ -20,6 +20,7 @@
#define CONTACT_IMAGES_ENABLED_KEY @"Contact Images Enabled Key"
#define AUTOCORRECT_ENABLED_KEY @"Autocorrect Enabled Key"
#define HISTORY_LOG_ENABLED_KEY @"History Log Enabled Key"
#define PUSH_REVOKED_KEY @"Push Revoked Key"
@implementation PropertyListPreferences (PropertyUtil)
@ -107,4 +108,11 @@
[self setValueForKey:HISTORY_LOG_ENABLED_KEY toValue:[NSNumber numberWithBool:enabled]];
}
-(BOOL) encounteredRevokedPushPermission{
return [[self tryGetValueForKey:PUSH_REVOKED_KEY] boolValue];
}
-(void) setRevokedPushPermission:(BOOL)revoked{
[self setValueForKey:PUSH_REVOKED_KEY toValue:[NSNumber numberWithBool:revoked]];
}
@end

View File

@ -0,0 +1,23 @@
//
// PushManager.h
// Signal
//
// Created by Frederic Jacobs on 31/07/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface PushManager : NSObject
+ (instancetype)sharedManager;
- (void)verifyPushActivated;
- (void)askForPushRegistration;
- (void)registerForPushWithToken:(NSData*)token;
@end

View File

@ -0,0 +1,88 @@
//
// PushManager.m
// Signal
//
// Created by Frederic Jacobs on 31/07/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "PreferencesUtil.h"
#import "PushManager.h"
#import "Environment.h"
#import "CallServerRequestsManager.h"
@interface PushManager ()
@property int retries;
@end
@implementation PushManager
+ (instancetype)sharedManager {
static PushManager *sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedManager = [[self alloc] init];
});
return sharedManager;
}
- (void)verifyPushActivated{
UIRemoteNotificationType notificationTypes = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
BOOL needsPushSettingChangeAlert = NO;
// enhancement: do custom message depending on the setting?
if (notificationTypes == UIRemoteNotificationTypeNone) {
needsPushSettingChangeAlert = YES;
} else if (notificationTypes == UIRemoteNotificationTypeBadge) {
needsPushSettingChangeAlert = YES;
} else if (notificationTypes == UIRemoteNotificationTypeAlert) {
needsPushSettingChangeAlert = YES;
} else if (notificationTypes == UIRemoteNotificationTypeSound) {
needsPushSettingChangeAlert = YES;
} else if (notificationTypes == (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert)) {
needsPushSettingChangeAlert = YES;
} else if (notificationTypes == (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)) {
needsPushSettingChangeAlert = YES;
}
if (needsPushSettingChangeAlert) {
[[Environment preferences] setRevokedPushPermission:YES];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"ACTION_REQUIRED_TITLE", @"") message:NSLocalizedString(@"PUSH_SETTINGS_MESSAGE", @"") delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", @"") otherButtonTitles:nil, nil];
[alertView show];
} else if (!needsPushSettingChangeAlert){
if ([[Environment preferences] encounteredRevokedPushPermission]) {
[self askForPushRegistration];
}
}
}
- (void)askForPushRegistration{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeBadge)];
self.retries = 3;
}
- (void)registerForPushWithToken:(NSData*)token{
[[CallServerRequestsManager sharedManager] registerPushToken:token success:^(NSURLSessionDataTask *task, id responseObject) {
if ([task.response isKindOfClass: [NSHTTPURLResponse class]]){
NSInteger statusCode = [(NSHTTPURLResponse*) task.response statusCode];
if (statusCode == 200) {
DDLogInfo(@"Device sent push ID to server");
[[Environment preferences] setRevokedPushPermission:NO];
}
}
} failure:^(NSURLSessionDataTask *task, NSError *error) {
if (self.retries > 0) {
[self registerForPushWithToken:token];
self.retries--;
} else{
[[Environment preferences] setRevokedPushPermission:YES];
}
}];
}
@end

View File

@ -0,0 +1,18 @@
//
// CallServerRequests.h
// Signal
//
// Created by Frederic Jacobs on 31/07/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <AFNetworking/AFNetworking.h>
@interface CallServerRequestsManager : NSObject
+ (instancetype)sharedManager;
- (void)registerPushToken:(NSData*)deviceToken success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure;
@end

View File

@ -0,0 +1,63 @@
//
// CallServerRequests.m
// Signal
//
// Created by Frederic Jacobs on 31/07/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "HttpRequest.h"
#import "CallServerRequestsManager.h"
#import "DataUtil.h"
#import "Environment.h"
#import "HostNameEndPoint.h"
#import "SGNKeychainUtil.h"
#define defaultRequestTimeout
@interface CallServerRequestsManager ()
@property (nonatomic, retain)AFHTTPSessionManager *operationManager;
@end
@implementation CallServerRequestsManager
+ (instancetype)sharedManager {
static CallServerRequestsManager *sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedManager = [[self alloc] init];
});
return sharedManager;
}
- (id)init{
self = [super init];
if (self) {
HostNameEndPoint *endpoint = [[[Environment getCurrent]masterServerSecureEndPoint] hostNameEndPoint];
NSURL *endPointURL = [NSURL URLWithString:[NSString stringWithFormat:@"https://%@:%hu", endpoint.hostname, endpoint.port]];
NSURLSessionConfiguration *sessionConf = [NSURLSessionConfiguration ephemeralSessionConfiguration];
self.operationManager = [[AFHTTPSessionManager alloc] initWithBaseURL:endPointURL sessionConfiguration:sessionConf];
[self.operationManager setSecurityPolicy:[AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone]];
self.operationManager.securityPolicy.allowInvalidCertificates = YES; // We use a custom certificate, not signed by a CA.
self.operationManager.responseSerializer = [AFJSONResponseSerializer serializer];
}
return self;
}
- (void)registerPushToken:(NSData*)deviceToken success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure{
self.operationManager.requestSerializer = [self basicAuthenticationSerializer];
[self.operationManager PUT:[NSString stringWithFormat:@"/apn/%@",[deviceToken encodedAsHexString]] parameters:@{} success:success failure:failure];
}
- (AFHTTPRequestSerializer*)basicAuthenticationSerializer{
AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
[serializer setValue:[HttpRequest computeBasicAuthorizationTokenForLocalNumber:[SGNKeychainUtil localNumber]andPassword:[SGNKeychainUtil serverAuthPassword]] forHTTPHeaderField:@"Authorization"];
return serializer;
}
@end

View File

@ -99,8 +99,6 @@
NSString* query = [NSString stringWithFormat:@"/apn/%@", [deviceToken encodedAsHexString]];
DDLogInfo(@"Registered APN Device Token with Signal Server");
return [HttpRequest httpRequestWithBasicAuthenticationAndMethod:@"PUT"
andLocation:query];
}

View File

@ -24,7 +24,7 @@
-(void) startUntilCancelled:(id<CancelToken>)cancelToken {
lifetimeToken = cancelToken;
phoneNumberDirectoryFilter = [[[Environment getCurrent] preferences] tryGetSavedPhoneNumberDirectory];
phoneNumberDirectoryFilter = [[Environment preferences] tryGetSavedPhoneNumberDirectory];
if (phoneNumberDirectoryFilter == nil) {
phoneNumberDirectoryFilter = [PhoneNumberDirectoryFilter phoneNumberDirectoryFilterDefault];
}
@ -103,7 +103,7 @@
@synchronized(self) {
phoneNumberDirectoryFilter = directory;
}
[[[Environment getCurrent]preferences] setSavedPhoneNumberDirectory:directory];
[[Environment preferences] setSavedPhoneNumberDirectory:directory];
[[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_DIRECTORY_WAS_UPDATED object:nil];
[self scheduleUpdate];
}];

View File

@ -22,6 +22,5 @@
@property (nonatomic, strong) IBOutlet UILabel *freshAppTutorialMiddleLabel;
@property (nonatomic, assign) FutureSource *apnId;
@end

View File

@ -49,7 +49,7 @@ static NSString *const FOOTER_TABLE_CELL_IDENTIFIER = @"InboxFeedFooterCell";
[self setupLabelLocalizationAndStyles];
if (![Environment isRegistered]) {
RegisterViewController *registerViewController = [RegisterViewController registerViewControllerForApn:_apnId];
RegisterViewController *registerViewController = [RegisterViewController registerViewController];
[self presentViewController:registerViewController animated:NO completion:nil];
}
_inboxFeedTableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
@ -181,7 +181,7 @@ static NSString *const FOOTER_TABLE_CELL_IDENTIFIER = @"InboxFeedFooterCell";
}
- (void)updateTutorialVisibility {
_freshInboxView.hidden = ![[[Environment getCurrent] preferences] getFreshInstallTutorialsEnabled];
_freshInboxView.hidden = ![[Environment preferences] getFreshInstallTutorialsEnabled];
_inboxFeedTableView.hidden = !_freshInboxView.hidden;
}

View File

@ -5,7 +5,6 @@
#import "FutureSource.h"
@interface RegisterViewController : UIViewController <CountryCodeViewControllerDelegate, UITextFieldDelegate> {
@private Future* futureApnId;
@private FutureSource* registered;
@private FutureSource* futureChallengeAcceptedSource;
@private CancelTokenSource* life;
@ -36,6 +35,6 @@
- (IBAction)changeCountryCodeTapped;
- (IBAction)initiateVoiceVerificationButtonHandler;
+ (RegisterViewController*)registerViewControllerForApn:(Future *)apnId;
+ (RegisterViewController*)registerViewController;
@end

View File

@ -6,6 +6,7 @@
#import "PhoneNumberDirectoryFilterManager.h"
#import "PhoneNumberUtil.h"
#import "PreferencesUtil.h"
#import "PushManager.h"
#import "RegisterViewController.h"
#import "SignalUtil.h"
#import "SGNKeychainUtil.h"
@ -52,11 +53,8 @@
_enteredPhoneNumber = [NSMutableString string];
}
+ (RegisterViewController*)registerViewControllerForApn:(Future *)apnId {
require(apnId != nil);
+ (RegisterViewController*)registerViewController {
RegisterViewController *viewController = [RegisterViewController new];
viewController->futureApnId = apnId;
viewController->registered = [FutureSource new];
viewController->life = [CancelTokenSource cancelTokenSource];
[[viewController->life getToken] whenCancelledTryCancel:viewController->registered];
@ -133,7 +131,7 @@
againstTimeout:20.0
untilCancelled:cancelToken];
Future *futurePhoneRegistrationVerified = [futurePhoneRegistrationStarted then:^(id _) {
return [futurePhoneRegistrationStarted then:^(id _) {
[self showViewNumber:CHALLENGE_VIEW_NUMBER];
[Environment setRegistered:YES];
[self.challengeNumberLabel setText:[phoneNumber description]];
@ -143,24 +141,6 @@
return futureChallengeAcceptedSource;
}];
Future *futureApnToRegister = [futurePhoneRegistrationVerified then:^(HttpResponse* okResponse) {
return [futureApnId catch:^id(id error) {
DDLogError(@"Could not get APN. Runs in Simulator?");
return nil;
}];
}];
return [futureApnToRegister then:^Future*(NSData* deviceToken) {
if (deviceToken == nil){
DDLogError(@"Couldn't get a device token for APN. Runs in Simulator?");
return futureApnToRegister;
}
HttpRequest* request = [HttpRequest httpRequestToRegisterForApnSignalingWithDeviceToken:deviceToken];
return [HttpManager asyncOkResponseFromMasterServer:request
unlessCancelled:cancelToken
andErrorHandler:[Environment errorNoter]];
}];
}
- (void)registerPhoneNumberTapped {
@ -219,6 +199,7 @@
[registered trySetResult:@YES];
[self dismissView];
[futureChallengeAcceptedSource trySetResult:result];
[[PushManager sharedManager] askForPushRegistration];
}];
[futureDone finallyDo:^(Future *completed) {

View File

@ -35,8 +35,6 @@
@property (nonatomic, strong) IBOutlet UITableViewCell *sendDebugLog;
@property (nonatomic, assign) FutureSource *apnId;
- (IBAction)registerTapped;
- (IBAction)privacyAndSecurityTapped;

View File

@ -106,7 +106,7 @@ static NSString *const CHECKBOX_EMPTY_IMAGE_NAME = @"checkbox_empty";
[button setImage:[UIImage imageNamed:CHECKBOX_CHECKMARK_IMAGE_NAME]
forState:UIControlStateSelected];
}
PropertyListPreferences *prefs = [[Environment getCurrent] preferences];
PropertyListPreferences *prefs = [Environment preferences];
_hideContactImagesButton.selected = ![prefs getContactImagesEnabled];
_disableAutocorrectButton.selected = ![prefs getAutocorrectEnabled];
_disableHistoryButton.selected = ![prefs getHistoryLogEnabled];
@ -155,7 +155,7 @@ static NSString *const CHECKBOX_EMPTY_IMAGE_NAME = @"checkbox_empty";
#pragma mark - Actions
- (void)registerTapped {
RegisterViewController *registerViewController = [RegisterViewController registerViewControllerForApn:_apnId];
RegisterViewController *registerViewController = [RegisterViewController registerViewController];
[self presentViewController:registerViewController animated:YES completion:nil];
}
@ -181,17 +181,17 @@ static NSString *const CHECKBOX_EMPTY_IMAGE_NAME = @"checkbox_empty";
- (IBAction)hideContactImagesButtonTapped {
_hideContactImagesButton.selected = !_hideContactImagesButton.selected;
[[[Environment getCurrent] preferences] setContactImagesEnabled:!_hideContactImagesButton.selected];
[[Environment preferences] setContactImagesEnabled:!_hideContactImagesButton.selected];
}
- (IBAction)disableAutocorrectButtonTapped {
_disableAutocorrectButton.selected = !_disableAutocorrectButton.selected;
[[[Environment getCurrent] preferences] setAutocorrectEnabled:!_disableAutocorrectButton.selected];
[[Environment preferences] setAutocorrectEnabled:!_disableAutocorrectButton.selected];
}
- (IBAction)disableHistoryButtonTapped {
_disableHistoryButton.selected = !_disableHistoryButton.selected;
[[[Environment getCurrent] preferences] setHistoryLogEnabled:!_disableHistoryButton.selected];
[[Environment preferences] setHistoryLogEnabled:!_disableHistoryButton.selected];
}
- (void)clearHistory {

View File

@ -43,7 +43,6 @@
_inviteContactsNavigationController = [[UINavigationController alloc] initWithRootViewController:_inviteContactsViewController];
_contactsViewController = [ContactBrowseViewController new];
_contactNavigationController = [[UINavigationController alloc] initWithRootViewController:_contactsViewController];
[[AppAudioManager sharedInstance] requestRequiredPermissionsIfNeeded];
}
return self;
}

View File

@ -65,7 +65,7 @@
}
- (void)updateAutoCorrectionType {
BOOL autoCorrectEnabled = [[[Environment getCurrent] preferences] getAutocorrectEnabled];
BOOL autoCorrectEnabled = [[Environment preferences] getAutocorrectEnabled];
_searchTextField.autocorrectionType = autoCorrectEnabled ? UITextAutocorrectionTypeYes : UITextAutocorrectionTypeNo;
}

View File

@ -18,7 +18,7 @@
[Environment setCurrent:testEnv];
[SGNKeychainUtil setLocalNumberTo:[PhoneNumber phoneNumberFromE164:@"+19025555555"]];
[UICKeyChainStore setString:@"shall_not_password" forKey:@"Password"];
[[[Environment getCurrent] preferences] setValueForKey:@"PasswordCounter" toValue:@2357];
[[Environment preferences] setValueForKey:@"PasswordCounter" toValue:@2357];
HttpRequest* h = [HttpRequest httpRequestToInitiateToRemoteNumber:[PhoneNumber phoneNumberFromE164:@"+19023334444"]];
test([[h method] isEqualToString:@"GET"]);
test([[h location] isEqualToString:@"/session/1/+19023334444"]);

View File

@ -38,8 +38,8 @@
};
[Environment setCurrent:testEnv];
[[[Environment getCurrent] preferences] setValueForKey:@"Signaling Mac Key" toValue:[@"0000000000000000000000000000000000000000" decodedAsHexString]];
[[[Environment getCurrent]preferences] setValueForKey:@"Signaling Cipher Key" toValue:[@"00000000000000000000000000000000" decodedAsHexString]];
[[Environment preferences] setValueForKey:@"Signaling Mac Key" toValue:[@"0000000000000000000000000000000000000000" decodedAsHexString]];
[[Environment preferences] setValueForKey:@"Signaling Cipher Key" toValue:[@"00000000000000000000000000000000" decodedAsHexString]];
ResponderSessionDescriptor* d = [ResponderSessionDescriptor responderSessionDescriptorFromEncryptedRemoteNotification:notification];

View File

@ -69,7 +69,6 @@
uint16_t b = [CryptoTools generateSecureRandomUInt16];
uint16_t c = [CryptoTools generateSecureRandomUInt16];
uint16_t d = [CryptoTools generateSecureRandomUInt16];
int n = sizeof(uint32_t);
// extremely unlikely to fail if any reasonable amount of entropy is going into d and d2
test(!(a==b==c==d));
}

View File

@ -1,5 +1,7 @@
"ACTION_REQUIRED_TITLE" = "Action Required";
"ANSWER_CALL_BUTTON_TITLE" = "Answer";
"APN" = "Incoming Call";
"AUDIO_PERMISSION_MESSAGE" = "Signal requires access to your microphone to work properly. You can restore the permission in the Settings app >> Privacy >> Microphone >> Signal";
"CALL_BUTTON_TITLE" = "Call";
"CHALLENGE_CODE_BUTTON_TITLE" = "VERIFY";
"CHOOSE_COUNTRY_CODE" = "Choose Country Code";
@ -33,7 +35,6 @@
"DIALER_NUMBER_8" = "8";
"DIALER_NUMBER_9" = "9";
"DIALER_NUMBER_PLUS" = "+";
"DIALER_NUMBER_PLUS" = "+";
"DIALER_NUMBER_POUND" = "#";
"DISABLING_BACKUP_FAILED" = "We encountered an issue while disabling the backup of your call log. Call logs might leak in your iTunes/iCloud backups.";
"END_CALL_BAD_INTERACTION_WITH_SERVER" = "Server Failed!";
@ -85,6 +86,7 @@
"NOTIFICATION_TEXT" = "Some of your contacts have recently registered numbers with Signal!";
"NO_FAVOURITES_TEXT" = "To favorite a contact, tap the star on a contact page.";
"OK" = "Ok";
"PUSH_SETTINGS_MESSAGE" = "Signal requires push notification alerts and sounds to be enabled to work properly. Please change it in the Settings app >> Notification Center >> Signal.";
"QUICK_LINKS_TITLE" = "Quick Links";
"RECENT_CALLS_SORTING_TITLE" = "Sorting Method";
"RECENT_NAV_BAR_TITLE" = "Call Log";
@ -102,12 +104,10 @@
"REGISTER_TEXTBLOCK" = "To get started making secure calls, please confirm your country code and enter your device's phone number.";
"REGISTER_VALIDATION_ENTER_CODE" = "Validation Code";
"REGISTER_VALIDATION_SENT" = "We sent your validation code";
"REGISTER_WELCOME_TEXT" = "Welcome to Signal";
"REGISTRATION_ERROR" = "Registration Error";
"REGISTRATION_BODY" = "We couldn't reach the Signal server. Please try again.";
"REJECT_CALL_BUTTON_TITLE" = "Reject";
"SETTINGS_ANONYMOUS_FEEDBACK" = "Send Anonymous Feedback";
"SETTINGS_CALL_QUALITY" = "Call Quality";
"SETTINGS_CHANGE_VOLUME" = "Change Volume With Buttons";
"SETTINGS_CLEAR_HISTORY_LOG" = "Clear History Log";