2014-08-01 07:53:58 +02:00
//
// 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"
2014-09-15 01:32:19 +02:00
# import "FutureUtil.h"
2014-08-01 07:53:58 +02:00
@ interface PushManager ( )
2014-09-15 01:32:19 +02:00
@ property TOCFutureSource * registerWithServerFutureSource ;
2014-08-02 13:57:50 +02:00
2014-09-15 01:32:19 +02:00
@ property UIAlertView * missingPermissionsAlertView ;
2014-08-01 07:53:58 +02:00
@ end
@ implementation PushManager
+ ( instancetype ) sharedManager {
static PushManager * sharedManager = nil ;
static dispatch_once _t onceToken ;
dispatch_once ( & onceToken , ^ {
2014-09-08 01:31:05 +02:00
sharedManager = [ self new ] ;
2014-09-15 01:32:19 +02:00
sharedManager . missingPermissionsAlertView = [ [ UIAlertView alloc ] initWithTitle : NSLocalizedString ( @ "ACTION_REQUIRED_TITLE" , @ "" ) message : NSLocalizedString ( @ "PUSH_SETTINGS_MESSAGE" , @ "" ) delegate : nil cancelButtonTitle : NSLocalizedString ( @ "OK" , @ "" ) otherButtonTitles : nil , nil ] ;
2014-08-01 07:53:58 +02:00
} ) ;
return sharedManager ;
}
2014-09-15 01:32:19 +02:00
- ( void ) verifyPushPermissions {
2014-08-01 07:53:58 +02:00
2014-09-15 01:32:19 +02:00
if ( SYSTEM_VERSION _LESS _THAN ( _iOS _8 _0 ) ) {
// Displaying notifications and ringing
if ( [ self isMissingMandatoryNotificationTypes : [ UIApplication . sharedApplication enabledRemoteNotificationTypes ] ] ) {
[ self registrationWithSuccess : ^ {
DDLogInfo ( @ "Push notifications were succesfully re-enabled" ) ;
} failure : ^ {
[ self . missingPermissionsAlertView show ] ;
} ] ;
}
} else {
// UIUserNotificationsSettings
UIUserNotificationSettings * settings = [ UIApplication . sharedApplication currentUserNotificationSettings ] ;
// To use Signal , it is required to have sound notifications and alert types .
if ( [ self isMissingMandatoryNotificationTypes : settings . types ] ) {
[ self registrationForUserNotificationWithSuccess : ^ {
DDLogInfo ( @ "User notifications were succesfully re-enabled" ) ;
} failure : ^ {
[ self . missingPermissionsAlertView show ] ;
} ] ;
}
// Remote Notifications
if ( ! [ UIApplication . sharedApplication isRegisteredForRemoteNotifications ] ) {
[ self registrationForPushWithSuccess : ^ {
DDLogInfo ( @ "Push notification were succesfully re-enabled" ) ;
} failure : ^ {
DDLogError ( @ "The phone could not be re-registered for push notifications." ) ; // Push tokens are not changing on the same phone , just user notification changes so it ' s not very important .
} ] ;
2014-08-01 07:53:58 +02:00
}
}
2014-08-02 13:57:50 +02:00
}
2014-09-15 01:32:19 +02:00
- ( void ) registrationWithSuccess : ( void ( ^ ) ( ) ) success failure : ( void ( ^ ) ( ) ) failure {
2014-08-05 05:44:43 +02:00
2014-09-15 01:32:19 +02:00
if ( SYSTEM_VERSION _LESS _THAN ( _iOS _8 _0 ) ) {
// On iOS7 , we just need to register for Push Notifications ( user notifications are enabled with them )
[ self registrationForPushWithSuccess : success failure : failure ] ;
2014-08-05 05:44:43 +02:00
2014-09-15 01:32:19 +02:00
} else {
2014-08-05 05:44:43 +02:00
2014-09-15 01:32:19 +02:00
// On iOS 8 + , both Push Notifications and User Notfications need to be registered .
2014-08-05 05:44:43 +02:00
2014-09-15 01:32:19 +02:00
[ self registrationForPushWithSuccess : ^ {
[ self registrationForUserNotificationWithSuccess : success failure : ^ {
[ self . missingPermissionsAlertView show ] ;
failure ( ) ;
} ] ;
} failure : failure ] ;
2014-08-05 05:44:43 +02:00
}
2014-08-01 07:53:58 +02:00
}
2014-09-15 01:32:19 +02:00
# pragma mark Private Methods
# pragma mark Register Push Notification Token with server
- ( TOCFuture * ) registerForPushFutureWithToken : ( NSData * ) token {
self . registerWithServerFutureSource = [ TOCFutureSource new ] ;
2014-08-19 06:14:19 +02:00
[ CallServerRequestsManager . sharedInstance registerPushToken : token success : ^ ( NSURLSessionDataTask * task , id responseObject ) {
2014-09-08 01:31:05 +02:00
if ( [ task . response isKindOfClass : NSHTTPURLResponse . class ] ) {
2014-08-01 07:53:58 +02:00
NSInteger statusCode = [ ( NSHTTPURLResponse * ) task . response statusCode ] ;
if ( statusCode = = 200 ) {
2014-09-15 01:32:19 +02:00
[ self . registerWithServerFutureSource trySetResult : @ YES ] ;
2014-08-02 13:57:50 +02:00
} else {
2014-09-15 01:32:19 +02:00
DDLogError ( @ "The server returned %@ instead of a 200 status code" , task . response ) ;
[ self . registerWithServerFutureSource trySetFailure : @ NO ] ;
2014-08-01 07:53:58 +02:00
}
2014-09-15 01:32:19 +02:00
} else {
[ self . registerWithServerFutureSource trySetFailure : @ NO ] ;
2014-08-01 07:53:58 +02:00
}
} failure : ^ ( NSURLSessionDataTask * task , NSError * error ) {
2014-09-15 01:32:19 +02:00
[ self . registerWithServerFutureSource trySetFailure : @ NO ] ;
2014-08-01 07:53:58 +02:00
} ] ;
2014-09-15 01:32:19 +02:00
return self . registerWithServerFutureSource . future ;
}
# pragma mark Register device for Push Notification locally
- ( TOCFuture * ) registeriOS7PushNotificationFuture {
self . pushNotificationFutureSource = [ TOCFutureSource new ] ;
[ UIApplication . sharedApplication registerForRemoteNotificationTypes : ( UIRemoteNotificationType ) [ self mandatoryNotificationTypes ] ] ;
return self . pushNotificationFutureSource . future ;
2014-08-01 07:53:58 +02:00
}
2014-09-15 01:32:19 +02:00
- ( TOCFuture * ) registerPushNotificationFuture {
self . pushNotificationFutureSource = [ TOCFutureSource new ] ;
[ [ UIApplication sharedApplication ] registerForRemoteNotifications ] ;
return self . pushNotificationFutureSource . future ;
}
2014-08-01 07:53:58 +02:00
2014-09-15 01:32:19 +02:00
- ( TOCFuture * ) registerForUserNotificationsFuture {
self . userNotificationFutureSource = [ TOCFutureSource new ] ;
[ UIApplication . sharedApplication registerUserNotificationSettings : [ UIUserNotificationSettings settingsForTypes : ( UIUserNotificationType ) [ self allNotificationTypes ] categories : [ NSSet setWithObject : [ self userNotificationsCallCategory ] ] ] ] ;
return self . userNotificationFutureSource . future ;
}
2014-08-02 13:57:50 +02:00
2014-09-15 01:32:19 +02:00
- ( void ) registrationForPushWithSuccess : ( void ( ^ ) ( ) ) success failure : ( void ( ^ ) ( ) ) failure {
TOCFuture * requestPushTokenFuture ;
if ( SYSTEM_VERSION _LESS _THAN ( _iOS _8 _0 ) ) {
requestPushTokenFuture = [ self registeriOS7PushNotificationFuture ] ;
2014-08-02 13:57:50 +02:00
} else {
2014-09-15 01:32:19 +02:00
requestPushTokenFuture = [ self registerPushNotificationFuture ] ;
2014-08-02 13:57:50 +02:00
}
2014-09-15 01:32:19 +02:00
[ requestPushTokenFuture catchDo : ^ ( id failureObj ) {
failure ( ) ;
if ( SYSTEM_VERSION _LESS _THAN ( _iOS _8 _0 ) ) {
[ self . missingPermissionsAlertView show ] ;
} else {
DDLogError ( @ "This should not happen on iOS8. No push token was provided" ) ;
}
} ] ;
[ requestPushTokenFuture thenDo : ^ ( NSData * pushToken ) {
TOCFuture * registerPushTokenFuture = [ self registerForPushFutureWithToken : pushToken ] ;
[ registerPushTokenFuture catchDo : ^ ( id failureObj ) {
UIAlertView * failureToRegisterWithServerAlert = [ [ UIAlertView alloc ] initWithTitle : NSLocalizedString ( @ "REGISTRATION_ERROR" , @ "" ) message : NSLocalizedString ( @ "REGISTRATION_BODY" , nil ) delegate : nil cancelButtonTitle : NSLocalizedString ( @ "OK" , nil ) otherButtonTitles : nil , nil ] ;
[ failureToRegisterWithServerAlert show ] ;
failure ( ) ;
} ] ;
[ registerPushTokenFuture thenDo : ^ ( id value ) {
success ( ) ;
} ] ;
} ] ;
2014-08-02 13:57:50 +02:00
}
2014-09-15 01:32:19 +02:00
- ( void ) registrationForUserNotificationWithSuccess : ( void ( ^ ) ( ) ) success failure : ( void ( ^ ) ( ) ) failure {
TOCFuture * registrerUserNotificationFuture = [ self registerForUserNotificationsFuture ] ;
[ registrerUserNotificationFuture catchDo : ^ ( id failureObj ) {
[ self . missingPermissionsAlertView show ] ;
failure ( ) ;
} ] ;
[ registrerUserNotificationFuture thenDo : ^ ( id types ) {
if ( [ self isMissingMandatoryNotificationTypes : [ UIApplication . sharedApplication currentUserNotificationSettings ] . types ] ) {
[ self . missingPermissionsAlertView show ] ;
failure ( ) ;
} else {
success ( ) ;
}
} ] ;
}
- ( UIUserNotificationCategory * ) userNotificationsCallCategory {
UIMutableUserNotificationAction * action_accept = [ UIMutableUserNotificationAction new ] ;
action_accept . identifier = Signal_Accept _Identifier ;
action_accept . title = NSLocalizedString ( @ "ANSWER_CALL_BUTTON_TITLE" , @ "" ) ;
action_accept . activationMode = UIUserNotificationActivationModeForeground ;
action_accept . destructive = NO ;
action_accept . authenticationRequired = NO ;
UIMutableUserNotificationAction * action_decline = [ UIMutableUserNotificationAction new ] ;
action_decline . identifier = Signal_Decline _Identifier ;
action_decline . title = NSLocalizedString ( @ "REJECT_CALL_BUTTON_TITLE" , @ "" ) ;
action_decline . activationMode = UIUserNotificationActivationModeBackground ;
action_decline . destructive = NO ;
action_decline . authenticationRequired = NO ;
UIMutableUserNotificationCategory * callCategory = [ UIMutableUserNotificationCategory new ] ;
callCategory . identifier = @ "Signal_IncomingCall" ;
[ callCategory setActions : @ [ action_accept , action_decline ] forContext : UIUserNotificationActionContextMinimal ] ;
[ callCategory setActions : @ [ action_accept , action_decline ] forContext : UIUserNotificationActionContextDefault ] ;
return callCategory ;
}
- ( BOOL ) isMissingMandatoryNotificationTypes : ( int ) notificationTypes {
int mandatoryTypes = [ self mandatoryNotificationTypes ] ;
return ( ( mandatoryTypes & notificationTypes ) = = mandatoryTypes ) ? NO : YES ;
}
2014-08-05 05:44:43 +02:00
2014-09-15 01:32:19 +02:00
- ( int ) allNotificationTypes {
return ( UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge ) ;
}
- ( int ) mandatoryNotificationTypes {
return ( UIUserNotificationTypeAlert | UIUserNotificationTypeSound ) ;
}
2014-08-05 05:44:43 +02:00
2014-08-01 07:53:58 +02:00
@ end