session-ios/Signal/src/view controllers/CodeVerificationViewController.m

307 lines
11 KiB
Mathematica
Raw Normal View History

2014-10-29 21:58:58 +01:00
//
// CodeVerificationViewController.m
// Signal
//
// Created by Dylan Bourgeois on 13/11/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "CodeVerificationViewController.h"
2016-04-08 09:47:41 +02:00
#import <SignalServiceKit/TSStorageManager+keyingMaterial.h>
#import "OWSContactsManager.h"
#import "Environment.h"
2014-11-20 21:36:20 +01:00
#import "LocalizableText.h"
#import "PushManager.h"
#import "RPAccountManager.h"
#import "RPServerRequestsManager.h"
2014-11-20 21:36:20 +01:00
#import "TSAccountManager.h"
2014-10-29 21:58:58 +01:00
@interface CodeVerificationViewController ()
@end
@implementation CodeVerificationViewController
- (void)viewDidLoad {
2014-10-29 21:58:58 +01:00
[super viewDidLoad];
[self initializeKeyboardHandlers];
_headerLabel.text = NSLocalizedString(@"VERIFICATION_HEADER", @"");
_challengeTextField.placeholder = NSLocalizedString(@"VERIFICATION_CHALLENGE_DEFAULT_TEXT", @"");
_challengeTextField.delegate = self;
[_challengeButton setTitle:NSLocalizedString(@"VERIFICATION_CHALLENGE_SUBMIT_CODE", @"")
forState:UIControlStateNormal];
[_sendCodeViaSMSAgainButton setTitle:NSLocalizedString(@"VERIFICATION_CHALLENGE_SUBMIT_AGAIN", @"")
forState:UIControlStateNormal];
[_sendCodeViaVoiceButton
setTitle:[@" " stringByAppendingString:NSLocalizedString(@"VERIFICATION_CHALLENGE_SEND_VIAVOICE", @"")]
forState:UIControlStateNormal];
[_changeNumberButton
setTitle:[@" " stringByAppendingString:NSLocalizedString(@"VERIFICATION_CHALLENGE_CHANGE_NUMBER", @"")]
forState:UIControlStateNormal];
2014-10-29 21:58:58 +01:00
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self enableServerActions:YES];
[_phoneNumberEntered setText:_formattedPhoneNumber];
2015-01-30 22:58:23 +01:00
[self adjustScreenSizes];
}
- (IBAction)verifyChallengeAction:(id)sender {
[self enableServerActions:NO];
2014-10-29 21:58:58 +01:00
[_challengeTextField resignFirstResponder];
[self registerWithSuccess:^{
[_submitCodeSpinner stopAnimating];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
[TSAccountManager didRegister];
dispatch_async(dispatch_get_main_queue(), ^{
[self.navigationController
dismissViewControllerAnimated:YES
completion:^{
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined ||
ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusRestricted) {
UIAlertController *controller = [UIAlertController
alertControllerWithTitle:NSLocalizedString(@"REGISTER_CONTACTS_WELCOME", nil)
message:NSLocalizedString(@"REGISTER_CONTACTS_BODY", nil)
preferredStyle:UIAlertControllerStyleAlert];
[controller addAction:[UIAlertAction
actionWithTitle:NSLocalizedString(
@"REGISTER_CONTACTS_CONTINUE", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[self setupContacts];
}]];
[[UIApplication sharedApplication]
.keyWindow.rootViewController presentViewController:controller
animated:YES
completion:nil];
} else {
[self setupContacts];
}
}];
});
});
iOS 9 Support - Fixing size classes rendering bugs. - Supporting native iOS San Francisco font. - Quick Reply - Settings now slide to the left as suggested in original designed opposed to modal. - Simplification of restraints on many screens. - Full-API compatiblity with iOS 9 and iOS 8 legacy support. - Customized AddressBook Permission prompt when restrictions are enabled. If user installed Signal previously and already approved access to Contacts, don't bugg him again. - Fixes crash in migration for users who installed Signal <2.1.3 but hadn't signed up yet. - Xcode 7 / iOS 9 Travis Support - Bitcode Support is disabled until it is better understood how exactly optimizations are performed. In a first time, we will split out the crypto code into a separate binary to make it easier to optimize the non-sensitive code. Blog post with more details coming. - Partial ATS support. We are running our own Certificate Authority at Open Whisper Systems. Signal is doing certificate pinning to verify that certificates were signed by our own CA. Unfortunately Apple's App Transport Security requires to hand over chain verification to their framework with no control over the trust store. We have filed a radar to get ATS features with pinned certificates. In the meanwhile, ATS is disabled on our domain. We also followed Amazon's recommendations for our S3 domain we use to upload/download attachments. (#891) - Implement a unified `AFSecurityOWSPolicy` pinning strategy accross libraries (AFNetworking RedPhone/TextSecure & SocketRocket).
2015-09-01 19:22:08 +02:00
}
failure:^(NSError *error) {
[self enableServerActions:YES];
[_submitCodeSpinner stopAnimating];
DDLogError(@"Error: %@", error.localizedDescription);
}];
iOS 9 Support - Fixing size classes rendering bugs. - Supporting native iOS San Francisco font. - Quick Reply - Settings now slide to the left as suggested in original designed opposed to modal. - Simplification of restraints on many screens. - Full-API compatiblity with iOS 9 and iOS 8 legacy support. - Customized AddressBook Permission prompt when restrictions are enabled. If user installed Signal previously and already approved access to Contacts, don't bugg him again. - Fixes crash in migration for users who installed Signal <2.1.3 but hadn't signed up yet. - Xcode 7 / iOS 9 Travis Support - Bitcode Support is disabled until it is better understood how exactly optimizations are performed. In a first time, we will split out the crypto code into a separate binary to make it easier to optimize the non-sensitive code. Blog post with more details coming. - Partial ATS support. We are running our own Certificate Authority at Open Whisper Systems. Signal is doing certificate pinning to verify that certificates were signed by our own CA. Unfortunately Apple's App Transport Security requires to hand over chain verification to their framework with no control over the trust store. We have filed a radar to get ATS features with pinned certificates. In the meanwhile, ATS is disabled on our domain. We also followed Amazon's recommendations for our S3 domain we use to upload/download attachments. (#891) - Implement a unified `AFSecurityOWSPolicy` pinning strategy accross libraries (AFNetworking RedPhone/TextSecure & SocketRocket).
2015-09-01 19:22:08 +02:00
}
- (void)setupContacts {
[[Environment getCurrent].contactsManager doAfterEnvironmentInitSetup];
[[PushManager sharedManager] validateUserNotificationSettings];
iOS 9 Support - Fixing size classes rendering bugs. - Supporting native iOS San Francisco font. - Quick Reply - Settings now slide to the left as suggested in original designed opposed to modal. - Simplification of restraints on many screens. - Full-API compatiblity with iOS 9 and iOS 8 legacy support. - Customized AddressBook Permission prompt when restrictions are enabled. If user installed Signal previously and already approved access to Contacts, don't bugg him again. - Fixes crash in migration for users who installed Signal <2.1.3 but hadn't signed up yet. - Xcode 7 / iOS 9 Travis Support - Bitcode Support is disabled until it is better understood how exactly optimizations are performed. In a first time, we will split out the crypto code into a separate binary to make it easier to optimize the non-sensitive code. Blog post with more details coming. - Partial ATS support. We are running our own Certificate Authority at Open Whisper Systems. Signal is doing certificate pinning to verify that certificates were signed by our own CA. Unfortunately Apple's App Transport Security requires to hand over chain verification to their framework with no control over the trust store. We have filed a radar to get ATS features with pinned certificates. In the meanwhile, ATS is disabled on our domain. We also followed Amazon's recommendations for our S3 domain we use to upload/download attachments. (#891) - Implement a unified `AFSecurityOWSPolicy` pinning strategy accross libraries (AFNetworking RedPhone/TextSecure & SocketRocket).
2015-09-01 19:22:08 +02:00
}
- (NSString *)validationCodeFromTextField {
return [_challengeTextField.text stringByReplacingOccurrencesOfString:@"-" withString:@""];
2014-10-29 21:58:58 +01:00
}
- (TOCFuture *)pushRegistration {
TOCFutureSource *pushAndRegisterFuture = [[TOCFutureSource alloc] init];
;
[[PushManager sharedManager] requestPushTokenWithSuccess:^(NSString *pushToken, NSString *voipToken) {
NSMutableArray *pushTokens = [NSMutableArray arrayWithObject:pushToken];
if (voipToken) {
[pushTokens addObject:voipToken];
}
[pushAndRegisterFuture trySetResult:pushTokens];
}
failure:^(NSError *error) {
[pushAndRegisterFuture trySetFailure:error];
}];
return pushAndRegisterFuture.future;
}
- (TOCFuture *)textSecureRegistrationFuture:(NSArray *)pushTokens {
TOCFutureSource *textsecureRegistration = [[TOCFutureSource alloc] init];
[TSAccountManager verifyAccountWithCode:[self validationCodeFromTextField]
pushToken:pushTokens[0]
voipToken:([pushTokens count] == 2) ? pushTokens.lastObject : nil
success:^{
[textsecureRegistration trySetResult:@YES];
}
failure:^(NSError *error) {
[textsecureRegistration trySetFailure:error];
}];
return textsecureRegistration.future;
}
- (void)registerWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure {
[_submitCodeSpinner startAnimating];
__block NSArray<NSString *> *pushTokens;
TOCFuture *tsRegistrationFuture = [[self pushRegistration] then:^id(NSArray<NSString *> *tokens) {
pushTokens = tokens;
return [self textSecureRegistrationFuture:pushTokens];
}];
TOCFuture *redphoneRegistrationFuture = [tsRegistrationFuture then:^id(id value) {
return [[self getRPRegistrationToken] then:^(NSString *registrationFuture) {
return [self redphoneRegistrationWithTSToken:registrationFuture
pushToken:pushTokens[0]
voipToken:([pushTokens count] == 2) ? pushTokens.lastObject : nil];
}];
}];
[redphoneRegistrationFuture thenDo:^(id value) {
success();
}];
[redphoneRegistrationFuture catchDo:^(NSError *error) {
failure(error);
}];
}
- (TOCFuture *)getRPRegistrationToken {
TOCFutureSource *redPhoneTokenFuture = [[TOCFutureSource alloc] init];
[TSAccountManager obtainRPRegistrationToken:^(NSString *rpRegistrationToken) {
[redPhoneTokenFuture trySetResult:rpRegistrationToken];
}
failure:^(NSError *error) {
[redPhoneTokenFuture trySetFailure:error];
}];
return redPhoneTokenFuture.future;
}
- (TOCFuture *)redphoneRegistrationWithTSToken:(NSString *)tsToken
pushToken:(NSString *)pushToken
voipToken:(NSString *)voipToken {
TOCFutureSource *rpRegistration = [[TOCFutureSource alloc] init];
[RPAccountManager registrationWithTsToken:tsToken
pushToken:pushToken
voipToken:voipToken
success:^{
[rpRegistration trySetResult:@YES];
}
failure:^(NSError *error) {
[rpRegistration trySetFailure:error];
}];
return rpRegistration.future;
}
#pragma mark - Send codes again
- (IBAction)sendCodeSMSAction:(id)sender {
[self enableServerActions:NO];
[_requestCodeAgainSpinner startAnimating];
[TSAccountManager rerequestSMSWithSuccess:^{
[self enableServerActions:YES];
[_requestCodeAgainSpinner stopAnimating];
}
failure:^(NSError *error) {
[self showRegistrationErrorMessage:error];
[self enableServerActions:YES];
[_requestCodeAgainSpinner stopAnimating];
}];
}
- (IBAction)sendCodeVoiceAction:(id)sender {
[self enableServerActions:NO];
[_requestCallSpinner startAnimating];
[TSAccountManager rerequestVoiceWithSuccess:^{
[self enableServerActions:YES];
[_requestCallSpinner stopAnimating];
}
failure:^(NSError *error) {
[self showRegistrationErrorMessage:error];
[self enableServerActions:YES];
[_requestCallSpinner stopAnimating];
}];
}
- (void)showRegistrationErrorMessage:(NSError *)registrationError {
UIAlertView *registrationErrorAV = [[UIAlertView alloc] initWithTitle:registrationError.localizedDescription
message:registrationError.localizedRecoverySuggestion
delegate:nil
cancelButtonTitle:REGISTER_ERROR_ALERT_VIEW_DISMISS
otherButtonTitles:nil, nil];
[registrationErrorAV show];
}
- (void)enableServerActions:(BOOL)enabled {
[_challengeButton setEnabled:enabled];
[_sendCodeViaSMSAgainButton setEnabled:enabled];
[_sendCodeViaVoiceButton setEnabled:enabled];
}
2014-10-29 21:58:58 +01:00
#pragma mark - Keyboard notifications
- (void)initializeKeyboardHandlers {
UITapGestureRecognizer *outsideTabRecognizer =
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)];
2014-10-29 21:58:58 +01:00
[self.view addGestureRecognizer:outsideTabRecognizer];
}
- (void)dismissKeyboardFromAppropriateSubView {
2014-10-29 21:58:58 +01:00
[self.view endEditing:NO];
}
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string {
if (range.location == 7) {
return NO;
}
if (range.length == 0 &&
![[NSCharacterSet decimalDigitCharacterSet] characterIsMember:[string characterAtIndex:0]]) {
return NO;
}
if (range.length == 0 && range.location == 3) {
textField.text = [NSString stringWithFormat:@"%@-%@", textField.text, string];
return NO;
}
if (range.length == 1 && range.location == 4) {
range.location--;
range.length = 2;
textField.text = [textField.text stringByReplacingCharactersInRange:range withString:@""];
return NO;
}
return YES;
}
- (void)adjustScreenSizes {
2015-01-30 22:58:23 +01:00
CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
CGFloat blueHeaderHeight;
if (screenHeight < 667) {
2015-01-30 22:58:23 +01:00
self.signalLogo.hidden = YES;
blueHeaderHeight = screenHeight - 400;
2015-01-30 22:58:23 +01:00
} else {
blueHeaderHeight = screenHeight - 410;
}
2015-01-30 22:58:23 +01:00
_headerConstraint.constant = blueHeaderHeight;
}
2014-10-29 21:58:58 +01:00
@end