@ -154,7 +154,7 @@ protocol CallServiceObserver: class {
Logger . debug ( " \( self . TAG ) .call setter: \( oldValue ? . identifiersForLogs as Optional ) -> \( call ? . identifiersForLogs as Optional ) " )
for observer in observers {
observer . value ? . didUpdateCall ( call : call )
observer . value ? . didUpdateCall ( call : call )
}
}
}
@ -227,13 +227,13 @@ protocol CallServiceObserver: class {
self . createCallUIAdapter ( )
NotificationCenter . default . addObserver ( self ,
selector : #selector ( didEnterBackground ) ,
name : NSNotification . Name . UIApplicationDidEnterBackground ,
object : nil )
selector : #selector ( didEnterBackground ) ,
name : NSNotification . Name . UIApplicationDidEnterBackground ,
object : nil )
NotificationCenter . default . addObserver ( self ,
selector : #selector ( didBecomeActive ) ,
name : NSNotification . Name . UIApplicationDidBecomeActive ,
object : nil )
selector : #selector ( didBecomeActive ) ,
name : NSNotification . Name . UIApplicationDidBecomeActive ,
object : nil )
}
deinit {
@ -275,8 +275,8 @@ protocol CallServiceObserver: class {
let errorDescription = " \( TAG ) call was unexpectedly already set. "
Logger . error ( errorDescription )
call . state = . localFailure
OWSProdError ( OWSAnalyticsEvents . callServiceCallAlreadySet ( ) , file : #file , function : #function , line : #line )
return Promise ( error : CallError . assertionError ( description : errorDescription ) )
OWSProdError ( OWSAnalyticsEvents . callServiceCallAlreadySet ( ) , file : #file , function : #function , line : #line )
return Promise ( error : CallError . assertionError ( description : errorDescription ) )
}
self . call = call
@ -292,14 +292,14 @@ protocol CallServiceObserver: class {
Logger . debug ( " \( self . TAG ) got ice servers: \( iceServers ) for call: \( call . identifiersForLogs ) " )
guard self . call = = call else {
throw CallError . obsoleteCall ( description : " obsolete call in \( #function ) " )
throw CallError . obsoleteCall ( description : " obsolete call in \( #function ) " )
}
guard self . peerConnectionClient = = nil else {
let errorDescription = " \( self . TAG ) peerconnection was unexpectedly already set. "
Logger . error ( errorDescription )
OWSProdError ( OWSAnalyticsEvents . callServicePeerConnectionAlreadySet ( ) , file : #file , function : #function , line : #line )
throw CallError . assertionError ( description : errorDescription )
OWSProdError ( OWSAnalyticsEvents . callServicePeerConnectionAlreadySet ( ) , file : #file , function : #function , line : #line )
throw CallError . assertionError ( description : errorDescription )
}
let useTurnOnly = Environment . getCurrent ( ) . preferences . doCallsHideIPAddress ( )
@ -312,11 +312,11 @@ protocol CallServiceObserver: class {
return peerConnectionClient . createOffer ( )
} . then { ( sessionDescription : HardenedRTCSessionDescription ) -> Promise < Void > in
guard self . call = = call else {
throw CallError . obsoleteCall ( description : " obsolete call in \( #function ) " )
throw CallError . obsoleteCall ( description : " obsolete call in \( #function ) " )
}
guard let peerConnectionClient = self . peerConnectionClient else {
owsFail ( " Missing peerConnectionClient in \( #function ) " )
throw CallError . obsoleteCall ( description : " Missing peerConnectionClient in \( #function ) " )
throw CallError . obsoleteCall ( description : " Missing peerConnectionClient in \( #function ) " )
}
return peerConnectionClient . setLocalSessionDescription ( sessionDescription ) . then {
@ -326,7 +326,7 @@ protocol CallServiceObserver: class {
}
} . then {
guard self . call = = call else {
throw CallError . obsoleteCall ( description : " obsolete call in \( #function ) " )
throw CallError . obsoleteCall ( description : " obsolete call in \( #function ) " )
}
// F o r o u t g o i n g c a l l s , w a i t u n t i l c a l l o f f e r i s s e n t b e f o r e w e s e n d a n y I C E u p d a t e s , t o e n s u r e m e s s a g e o r d e r i n g f o r
@ -340,7 +340,7 @@ protocol CallServiceObserver: class {
// D o n ' t l e t t h e o u t g o i n g c a l l r i n g f o r e v e r . W e d o n ' t s u p p o r t i n b o u n d r i n g i n g f o r e v e r a n y w a y .
let timeout : Promise < Void > = after ( interval : connectingTimeoutSeconds ) . then { ( ) -> Void in
// r e j e c t i n g a p r o m i s e b y t h r o w i n g i s s a f e l y a n o - o p i f t h e p r o m i s e h a s a l r e a d y b e e n f u l f i l l e d
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorTimeoutWhileConnectingOutgoing ( ) , file : #file , function : #function , line : #line )
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorTimeoutWhileConnectingOutgoing ( ) , file : #file , function : #function , line : #line )
throw CallError . timeout ( description : " timed out waiting to receive call answer " )
}
@ -353,10 +353,10 @@ protocol CallServiceObserver: class {
Logger . error ( " \( self . TAG ) placing call \( call . identifiersForLogs ) failed with error: \( error ) " )
if let callError = error as ? CallError {
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorOutgoingConnectionFailedInternal ( ) , file : #file , function : #function , line : #line )
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorOutgoingConnectionFailedInternal ( ) , file : #file , function : #function , line : #line )
self . handleFailedCall ( failedCall : call , error : callError )
} else {
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorOutgoingConnectionFailedExternal ( ) , file : #file , function : #function , line : #line )
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorOutgoingConnectionFailedExternal ( ) , file : #file , function : #function , line : #line )
let externalError = CallError . externalError ( underlyingError : error )
self . handleFailedCall ( failedCall : call , error : externalError )
}
@ -378,8 +378,8 @@ protocol CallServiceObserver: class {
}
guard let fulfillReadyToSendIceUpdatesPromise = self . fulfillReadyToSendIceUpdatesPromise else {
OWSProdError ( OWSAnalyticsEvents . callServiceMissingFulfillReadyToSendIceUpdatesPromise ( ) , file : #file , function : #function , line : #line )
self . handleFailedCall ( failedCall : call , error : CallError . assertionError ( description : " failed to create fulfillReadyToSendIceUpdatesPromise " ) )
OWSProdError ( OWSAnalyticsEvents . callServiceMissingFulfillReadyToSendIceUpdatesPromise ( ) , file : #file , function : #function , line : #line )
self . handleFailedCall ( failedCall : call , error : CallError . assertionError ( description : " failed to create fulfillReadyToSendIceUpdatesPromise " ) )
return
}
@ -417,8 +417,8 @@ protocol CallServiceObserver: class {
}
guard let peerConnectionClient = self . peerConnectionClient else {
OWSProdError ( OWSAnalyticsEvents . callServicePeerConnectionMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCall ( failedCall : call , error : CallError . assertionError ( description : " peerConnectionClient was unexpectedly nil in \( #function ) " ) )
OWSProdError ( OWSAnalyticsEvents . callServicePeerConnectionMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCall ( failedCall : call , error : CallError . assertionError ( description : " peerConnectionClient was unexpectedly nil in \( #function ) " ) )
return
}
@ -427,10 +427,10 @@ protocol CallServiceObserver: class {
Logger . debug ( " \( self . TAG ) successfully set remote description " )
} . catch { error in
if let callError = error as ? CallError {
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorHandleReceivedErrorInternal ( ) , file : #file , function : #function , line : #line )
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorHandleReceivedErrorInternal ( ) , file : #file , function : #function , line : #line )
self . handleFailedCall ( failedCall : call , error : callError )
} else {
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorHandleReceivedErrorExternal ( ) , file : #file , function : #function , line : #line )
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorHandleReceivedErrorExternal ( ) , file : #file , function : #function , line : #line )
let externalError = CallError . externalError ( underlyingError : error )
self . handleFailedCall ( failedCall : call , error : externalError )
}
@ -567,7 +567,7 @@ protocol CallServiceObserver: class {
case . idle , . dialing , . remoteRinging :
// I f b o t h u s e r s a r e t r y i n g t o c a l l e a c h o t h e r a t t h e s a m e t i m e ,
// b o t h s h o u l d s e e b u s y .
handleRemoteBusy ( thread : existingCall . thread , callId : existingCall . signalingId )
handleRemoteBusy ( thread : existingCall . thread , callId : existingCall . signalingId )
case . answering , . localRinging , . connected , . localFailure , . localHangup , . remoteHangup , . remoteBusy :
// I f o n e u s e r c a l l s a n o t h e r w h i l e t h e o t h e r h a s a " v e s t i g i a l " c a l l w i t h
// t h a t s a m e u s e r , f a i l t h e o l d c a l l .
@ -644,7 +644,7 @@ protocol CallServiceObserver: class {
let timeout : Promise < Void > = after ( interval : connectingTimeoutSeconds ) . then { ( ) -> Void in
// r e j e c t i n g a p r o m i s e b y t h r o w i n g i s s a f e l y a n o - o p i f t h e p r o m i s e h a s a l r e a d y b e e n f u l f i l l e d
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorTimeoutWhileConnectingIncoming ( ) , file : #file , function : #function , line : #line )
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorTimeoutWhileConnectingIncoming ( ) , file : #file , function : #function , line : #line )
throw CallError . timeout ( description : " timed out waiting for call to connect " )
}
@ -663,10 +663,10 @@ protocol CallServiceObserver: class {
return
}
if let callError = error as ? CallError {
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorIncomingConnectionFailedInternal ( ) , file : #file , function : #function , line : #line )
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorIncomingConnectionFailedInternal ( ) , file : #file , function : #function , line : #line )
self . handleFailedCall ( failedCall : newCall , error : callError )
} else {
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorIncomingConnectionFailedExternal ( ) , file : #file , function : #function , line : #line )
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorIncomingConnectionFailedExternal ( ) , file : #file , function : #function , line : #line )
let externalError = CallError . externalError ( underlyingError : error )
self . handleFailedCall ( failedCall : newCall , error : externalError )
}
@ -706,7 +706,7 @@ protocol CallServiceObserver: class {
peerConnectionClient . addRemoteIceCandidate ( RTCIceCandidate ( sdp : sdp , sdpMLineIndex : lineIndex , sdpMid : mid ) )
} . catch { error in
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorHandleRemoteAddedIceCandidate ( ) , file : #file , function : #function , line : #line )
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorHandleRemoteAddedIceCandidate ( ) , file : #file , function : #function , line : #line )
Logger . error ( " \( self . TAG ) in \( #function ) waitForPeerConnectionClient failed with error: \( error ) " )
} . retainUntilComplete ( )
}
@ -719,8 +719,8 @@ protocol CallServiceObserver: class {
AssertIsOnMainThread ( )
guard let call = self . call else {
OWSProdError ( OWSAnalyticsEvents . callServiceCallMissing ( ) , file : #file , function : #function , line : #line )
self . handleFailedCurrentCall ( error : CallError . assertionError ( description : " ignoring local ice candidate, since there is no current call. " ) )
OWSProdError ( OWSAnalyticsEvents . callServiceCallMissing ( ) , file : #file , function : #function , line : #line )
self . handleFailedCurrentCall ( error : CallError . assertionError ( description : " ignoring local ice candidate, since there is no current call. " ) )
return
}
@ -735,8 +735,8 @@ protocol CallServiceObserver: class {
guard call . state != . idle else {
// T h i s w i l l o n l y b e c a l l e d f o r t h e c u r r e n t p e e r C o n n e c t i o n C l i e n t , s o
// f a i l t h e c u r r e n t c a l l .
OWSProdError ( OWSAnalyticsEvents . callServiceCallUnexpectedlyIdle ( ) , file : #file , function : #function , line : #line )
self . handleFailedCurrentCall ( error : CallError . assertionError ( description : " ignoring local ice candidate, since call is now idle. " ) )
OWSProdError ( OWSAnalyticsEvents . callServiceCallUnexpectedlyIdle ( ) , file : #file , function : #function , line : #line )
self . handleFailedCurrentCall ( error : CallError . assertionError ( description : " ignoring local ice candidate, since call is now idle. " ) )
return
}
@ -756,7 +756,7 @@ protocol CallServiceObserver: class {
return
}
} . catch { error in
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorHandleLocalAddedIceCandidate ( ) , file : #file , function : #function , line : #line )
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorHandleLocalAddedIceCandidate ( ) , file : #file , function : #function , line : #line )
Logger . error ( " \( self . TAG ) in \( #function ) waitUntilReadyToSendIceUpdates failed with error: \( error ) " )
} . retainUntilComplete ( )
}
@ -773,8 +773,8 @@ protocol CallServiceObserver: class {
guard let call = self . call else {
// T h i s w i l l o n l y b e c a l l e d f o r t h e c u r r e n t p e e r C o n n e c t i o n C l i e n t , s o
// f a i l t h e c u r r e n t c a l l .
OWSProdError ( OWSAnalyticsEvents . callServiceCallMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCurrentCall ( error : CallError . assertionError ( description : " \( TAG ) ignoring \( #function ) since there is no current call. " ) )
OWSProdError ( OWSAnalyticsEvents . callServiceCallMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCurrentCall ( error : CallError . assertionError ( description : " \( TAG ) ignoring \( #function ) since there is no current call. " ) )
return
}
@ -848,16 +848,16 @@ protocol CallServiceObserver: class {
guard let call = self . call else {
// T h i s s h o u l d n e v e r h a p p e n ; r e t u r n t o a k n o w n g o o d s t a t e .
owsFail ( " \( TAG ) call was unexpectedly nil in \( #function ) " )
OWSProdError ( OWSAnalyticsEvents . callServiceCallMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCurrentCall ( error : CallError . assertionError ( description : " \( TAG ) call was unexpectedly nil in \( #function ) " ) )
OWSProdError ( OWSAnalyticsEvents . callServiceCallMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCurrentCall ( error : CallError . assertionError ( description : " \( TAG ) call was unexpectedly nil in \( #function ) " ) )
return
}
guard call . localId = = localId else {
// T h i s s h o u l d n e v e r h a p p e n ; r e t u r n t o a k n o w n g o o d s t a t e .
owsFail ( " \( TAG ) callLocalId: \( localId ) doesn't match current calls: \( call . localId ) " )
OWSProdError ( OWSAnalyticsEvents . callServiceCallIdMismatch ( ) , file : #file , function : #function , line : #line )
handleFailedCurrentCall ( error : CallError . assertionError ( description : " \( TAG ) callLocalId: \( localId ) doesn't match current calls: \( call . localId ) " ) )
OWSProdError ( OWSAnalyticsEvents . callServiceCallIdMismatch ( ) , file : #file , function : #function , line : #line )
handleFailedCurrentCall ( error : CallError . assertionError ( description : " \( TAG ) callLocalId: \( localId ) doesn't match current calls: \( call . localId ) " ) )
return
}
@ -873,8 +873,8 @@ protocol CallServiceObserver: class {
Logger . debug ( " \( TAG ) in \( #function ) " )
guard let currentCall = self . call else {
OWSProdError ( OWSAnalyticsEvents . callServiceCallMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCall ( failedCall : call , error : CallError . assertionError ( description : " \( TAG ) ignoring \( #function ) since there is no current call " ) )
OWSProdError ( OWSAnalyticsEvents . callServiceCallMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCall ( failedCall : call , error : CallError . assertionError ( description : " \( TAG ) ignoring \( #function ) since there is no current call " ) )
return
}
@ -886,8 +886,8 @@ protocol CallServiceObserver: class {
}
guard let peerConnectionClient = self . peerConnectionClient else {
OWSProdError ( OWSAnalyticsEvents . callServicePeerConnectionMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCall ( failedCall : call , error : CallError . assertionError ( description : " \( TAG ) missing peerconnection client in \( #function ) " ) )
OWSProdError ( OWSAnalyticsEvents . callServicePeerConnectionMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCall ( failedCall : call , error : CallError . assertionError ( description : " \( TAG ) missing peerconnection client in \( #function ) " ) )
return
}
@ -898,7 +898,7 @@ protocol CallServiceObserver: class {
call . callRecord = callRecord
let message = DataChannelMessage . forConnected ( callId : call . signalingId )
peerConnectionClient . sendDataChannelMessage ( data : message . asData ( ) , description : " connected " , isCritical : true )
peerConnectionClient . sendDataChannelMessage ( data : message . asData ( ) , description : " connected " , isCritical : true )
handleConnectedCall ( call )
}
@ -912,8 +912,8 @@ protocol CallServiceObserver: class {
AssertIsOnMainThread ( )
guard let peerConnectionClient = self . peerConnectionClient else {
OWSProdError ( OWSAnalyticsEvents . callServicePeerConnectionMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCall ( failedCall : call , error : CallError . assertionError ( description : " \( TAG ) peerConnectionClient unexpectedly nil in \( #function ) " ) )
OWSProdError ( OWSAnalyticsEvents . callServicePeerConnectionMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCall ( failedCall : call , error : CallError . assertionError ( description : " \( TAG ) peerConnectionClient unexpectedly nil in \( #function ) " ) )
return
}
@ -943,16 +943,16 @@ protocol CallServiceObserver: class {
guard let call = self . call else {
// T h i s s h o u l d n e v e r h a p p e n ; r e t u r n t o a k n o w n g o o d s t a t e .
owsFail ( " \( TAG ) call was unexpectedly nil in \( #function ) " )
OWSProdError ( OWSAnalyticsEvents . callServiceCallMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCurrentCall ( error : CallError . assertionError ( description : " \( TAG ) call was unexpectedly nil in \( #function ) " ) )
OWSProdError ( OWSAnalyticsEvents . callServiceCallMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCurrentCall ( error : CallError . assertionError ( description : " \( TAG ) call was unexpectedly nil in \( #function ) " ) )
return
}
guard call . localId = = localId else {
// T h i s s h o u l d n e v e r h a p p e n ; r e t u r n t o a k n o w n g o o d s t a t e .
owsFail ( " \( TAG ) callLocalId: \( localId ) doesn't match current calls: \( call . localId ) " )
OWSProdError ( OWSAnalyticsEvents . callServiceCallIdMismatch ( ) , file : #file , function : #function , line : #line )
handleFailedCurrentCall ( error : CallError . assertionError ( description : " \( TAG ) callLocalId: \( localId ) doesn't match current calls: \( call . localId ) " ) )
OWSProdError ( OWSAnalyticsEvents . callServiceCallIdMismatch ( ) , file : #file , function : #function , line : #line )
handleFailedCurrentCall ( error : CallError . assertionError ( description : " \( TAG ) callLocalId: \( localId ) doesn't match current calls: \( call . localId ) " ) )
return
}
@ -991,14 +991,14 @@ protocol CallServiceObserver: class {
AssertIsOnMainThread ( )
guard let currentCall = self . call else {
OWSProdError ( OWSAnalyticsEvents . callServiceCallMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCall ( failedCall : call , error : CallError . assertionError ( description : " \( TAG ) ignoring \( #function ) since there is no current call " ) )
OWSProdError ( OWSAnalyticsEvents . callServiceCallMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCall ( failedCall : call , error : CallError . assertionError ( description : " \( TAG ) ignoring \( #function ) since there is no current call " ) )
return
}
guard call = = currentCall else {
OWSProdError ( OWSAnalyticsEvents . callServiceCallMismatch ( ) , file : #file , function : #function , line : #line )
handleFailedCall ( failedCall : call , error : CallError . assertionError ( description : " \( TAG ) ignoring \( #function ) for call other than current call " ) )
OWSProdError ( OWSAnalyticsEvents . callServiceCallMismatch ( ) , file : #file , function : #function , line : #line )
handleFailedCall ( failedCall : call , error : CallError . assertionError ( description : " \( TAG ) ignoring \( #function ) for call other than current call " ) )
return
}
@ -1013,7 +1013,7 @@ protocol CallServiceObserver: class {
if let peerConnectionClient = self . peerConnectionClient {
// I f t h e c a l l i s c o n n e c t e d , w e c a n s e n d t h e h a n g u p v i a t h e d a t a c h a n n e l f o r f a s t e r h a n g u p .
let message = DataChannelMessage . forHangup ( callId : call . signalingId )
peerConnectionClient . sendDataChannelMessage ( data : message . asData ( ) , description : " hangup " , isCritical : true )
peerConnectionClient . sendDataChannelMessage ( data : message . asData ( ) , description : " hangup " , isCritical : true )
} else {
Logger . info ( " \( TAG ) ending call before peer connection created. Device offline or quick hangup. " )
}
@ -1024,7 +1024,7 @@ protocol CallServiceObserver: class {
let sendPromise = self . messageSender . sendPromise ( message : callMessage ) . then {
Logger . debug ( " \( self . TAG ) successfully sent hangup call message to \( call . thread . contactIdentifier ( ) ) " )
} . catch { error in
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorHandleLocalHungupCall ( ) , file : #file , function : #function , line : #line )
OWSProdInfo ( OWSAnalyticsEvents . callServiceErrorHandleLocalHungupCall ( ) , file : #file , function : #function , line : #line )
Logger . error ( " \( self . TAG ) failed to send hangup call message to \( call . thread . contactIdentifier ( ) ) with error: \( error ) " )
}
sendPromise . retainUntilComplete ( )
@ -1103,38 +1103,39 @@ protocol CallServiceObserver: class {
func setHasLocalVideo ( hasLocalVideo : Bool ) {
AssertIsOnMainThread ( )
let authStatus = AVCaptureDevice . authorizationStatus ( forMediaType : AVMediaTypeVideo )
switch authStatus {
case . notDetermined :
Logger . debug ( " \( TAG ) authStatus: AVAuthorizationStatusNotDetermined " )
break
case . restricted :
Logger . debug ( " \( TAG ) authStatus: AVAuthorizationStatusRestricted " )
break
case . denied :
Logger . debug ( " \( TAG ) authStatus: AVAuthorizationStatusDenied " )
break
case . authorized :
Logger . debug ( " \( TAG ) authStatus: AVAuthorizationStatusAuthorized " )
break
}
// W e d o n ' t n e e d t o w o r r y a b o u t t h e u s e r g r a n t i n g o r r e m o t i n g t h i s p e r m i s s i o n
// d u r i n g a c a l l w h i l e t h e a p p i s i n t h e b a c k g r o u n d , b e c a u s e c h a n g i n g t h i s
// p e r m i s s i o n k i l l s t h e a p p .
if authStatus != . authorized {
OWSAlerts . showAlert ( withTitle : NSLocalizedString ( " MISSING_CAMERA_PERMISSION_TITLE " , comment : " Alert title when camera is not authorized " ) ,
message : NSLocalizedString ( " MISSING_CAMERA_PERMISSION_MESSAGE " , comment : " Alert body when camera is not authorized " ) )
guard let frontmostViewController = UIApplication . shared . frontmostViewController else {
owsFail ( " \( TAG ) could not identify frontmostViewController in \( #function ) " )
return
}
frontmostViewController . ows_ask ( forCameraPermissions : { [ weak self ] granted in
guard let strongSelf = self else {
return
}
if ( granted ) {
// S u c c e s s c a l l b a c k ; c a m e r a p e r m i s s i o n s a r e g r a n t e d .
strongSelf . setHasLocalVideoWithCameraPermissions ( hasLocalVideo : hasLocalVideo )
} else {
// F a i l e d c a l l b a c k ; c a m e r a p e r m i s s i o n s a r e _ N O T _ g r a n t e d .
// W e d o n ' t n e e d t o w o r r y a b o u t t h e u s e r g r a n t i n g o r r e m o t i n g t h i s p e r m i s s i o n
// d u r i n g a c a l l w h i l e t h e a p p i s i n t h e b a c k g r o u n d , b e c a u s e c h a n g i n g t h i s
// p e r m i s s i o n k i l l s t h e a p p .
OWSAlerts . showAlert ( withTitle : NSLocalizedString ( " MISSING_CAMERA_PERMISSION_TITLE " , comment : " Alert title when camera is not authorized " ) ,
message : NSLocalizedString ( " MISSING_CAMERA_PERMISSION_MESSAGE " , comment : " Alert body when camera is not authorized " ) )
}
} )
}
private func setHasLocalVideoWithCameraPermissions ( hasLocalVideo : Bool ) {
AssertIsOnMainThread ( )
guard let call = self . call else {
// T h i s s h o u l d n e v e r h a p p e n ; r e t u r n t o a k n o w n g o o d s t a t e .
owsFail ( " \( TAG ) call was unexpectedly nil in \( #function ) " )
OWSProdError ( OWSAnalyticsEvents . callServiceCallMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCurrentCall ( error : CallError . assertionError ( description : " \( TAG ) call unexpectedly nil in \( #function ) " ) )
OWSProdError ( OWSAnalyticsEvents . callServiceCallMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCurrentCall ( error : CallError . assertionError ( description : " \( TAG ) call unexpectedly nil in \( #function ) " ) )
return
}
@ -1153,7 +1154,7 @@ protocol CallServiceObserver: class {
func handleCallKitStartVideo ( ) {
AssertIsOnMainThread ( )
self . setHasLocalVideo ( hasLocalVideo : true )
self . setHasLocalVideo ( hasLocalVideo : true )
}
/* *
@ -1172,8 +1173,8 @@ protocol CallServiceObserver: class {
guard let call = self . call else {
// T h i s s h o u l d n e v e r h a p p e n ; r e t u r n t o a k n o w n g o o d s t a t e .
owsFail ( " \( TAG ) received data message, but there is no current call. Ignoring. " )
OWSProdError ( OWSAnalyticsEvents . callServiceCallMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCurrentCall ( error : CallError . assertionError ( description : " \( TAG ) received data message, but there is no current call. Ignoring. " ) )
OWSProdError ( OWSAnalyticsEvents . callServiceCallMissing ( ) , file : #file , function : #function , line : #line )
handleFailedCurrentCall ( error : CallError . assertionError ( description : " \( TAG ) received data message, but there is no current call. Ignoring. " ) )
return
}
@ -1185,8 +1186,8 @@ protocol CallServiceObserver: class {
guard connected . id = = call . signalingId else {
// T h i s s h o u l d n e v e r h a p p e n ; r e t u r n t o a k n o w n g o o d s t a t e .
owsFail ( " \( TAG ) received connected message for call with id: \( connected . id ) but current call has id: \( call . signalingId ) " )
OWSProdError ( OWSAnalyticsEvents . callServiceCallIdMismatch ( ) , file : #file , function : #function , line : #line )
handleFailedCurrentCall ( error : CallError . assertionError ( description : " \( TAG ) received connected message for call with id: \( connected . id ) but current call has id: \( call . signalingId ) " ) )
OWSProdError ( OWSAnalyticsEvents . callServiceCallIdMismatch ( ) , file : #file , function : #function , line : #line )
handleFailedCurrentCall ( error : CallError . assertionError ( description : " \( TAG ) received connected message for call with id: \( connected . id ) but current call has id: \( call . signalingId ) " ) )
return
}
@ -1201,8 +1202,8 @@ protocol CallServiceObserver: class {
guard hangup . id = = call . signalingId else {
// T h i s s h o u l d n e v e r h a p p e n ; r e t u r n t o a k n o w n g o o d s t a t e .
owsFail ( " \( TAG ) received hangup message for call with id: \( hangup . id ) but current call has id: \( call . signalingId ) " )
OWSProdError ( OWSAnalyticsEvents . callServiceCallIdMismatch ( ) , file : #file , function : #function , line : #line )
handleFailedCurrentCall ( error : CallError . assertionError ( description : " \( TAG ) received hangup message for call with id: \( hangup . id ) but current call has id: \( call . signalingId ) " ) )
OWSProdError ( OWSAnalyticsEvents . callServiceCallIdMismatch ( ) , file : #file , function : #function , line : #line )
handleFailedCurrentCall ( error : CallError . assertionError ( description : " \( TAG ) received hangup message for call with id: \( hangup . id ) but current call has id: \( call . signalingId ) " ) )
return
}
@ -1309,8 +1310,8 @@ protocol CallServiceObserver: class {
}
guard let readyToSendIceUpdatesPromise = self . readyToSendIceUpdatesPromise else {
OWSProdError ( OWSAnalyticsEvents . callServiceCouldNotCreateReadyToSendIceUpdatesPromise ( ) , file : #file , function : #function , line : #line )
return Promise ( error : CallError . assertionError ( description : " failed to create readyToSendIceUpdatesPromise " ) )
OWSProdError ( OWSAnalyticsEvents . callServiceCouldNotCreateReadyToSendIceUpdatesPromise ( ) , file : #file , function : #function , line : #line )
return Promise ( error : CallError . assertionError ( description : " failed to create readyToSendIceUpdatesPromise " ) )
}
return readyToSendIceUpdatesPromise
@ -1353,8 +1354,8 @@ protocol CallServiceObserver: class {
}
guard let peerConnectionClientPromise = self . peerConnectionClientPromise else {
OWSProdError ( OWSAnalyticsEvents . callServiceCouldNotCreatePeerConnectionClientPromise ( ) , file : #file , function : #function , line : #line )
return Promise ( error : CallError . assertionError ( description : " failed to create peerConnectionClientPromise " ) )
OWSProdError ( OWSAnalyticsEvents . callServiceCouldNotCreatePeerConnectionClientPromise ( ) , file : #file , function : #function , line : #line )
return Promise ( error : CallError . assertionError ( description : " failed to create peerConnectionClientPromise " ) )
}
return peerConnectionClientPromise
@ -1576,8 +1577,8 @@ protocol CallServiceObserver: class {
self . peerConnectionClient ? . setLocalVideoEnabled ( enabled : shouldHaveLocalVideoTrack )
let message = DataChannelMessage . forVideoStreamingStatus ( callId : call . signalingId , enabled : shouldHaveLocalVideoTrack )
peerConnectionClient . sendDataChannelMessage ( data : message . asData ( ) , description : " videoStreamingStatus " )
let message = DataChannelMessage . forVideoStreamingStatus ( callId : call . signalingId , enabled : shouldHaveLocalVideoTrack )
peerConnectionClient . sendDataChannelMessage ( data : message . asData ( ) , description : " videoStreamingStatus " )
}
// MARK: - O b s e r v e r s
@ -1592,9 +1593,9 @@ protocol CallServiceObserver: class {
let call = self . call
let localVideoTrack = self . localVideoTrack
let remoteVideoTrack = self . isRemoteVideoEnabled ? self . remoteVideoTrack : nil
observer . didUpdateVideoTracks ( call : call ,
localVideoTrack : localVideoTrack ,
remoteVideoTrack : remoteVideoTrack )
observer . didUpdateVideoTracks ( call : call ,
localVideoTrack : localVideoTrack ,
remoteVideoTrack : remoteVideoTrack )
}
// T h e o b s e r v e r - r e l a t e d m e t h o d s s h o u l d b e i n v o k e d o n t h e m a i n t h r e a d .
@ -1621,9 +1622,9 @@ protocol CallServiceObserver: class {
let remoteVideoTrack = self . isRemoteVideoEnabled ? self . remoteVideoTrack : nil
for observer in observers {
observer . value ? . didUpdateVideoTracks ( call : call ,
localVideoTrack : localVideoTrack ,
remoteVideoTrack : remoteVideoTrack )
observer . value ? . didUpdateVideoTracks ( call : call ,
localVideoTrack : localVideoTrack ,
remoteVideoTrack : remoteVideoTrack )
}
}
@ -1669,7 +1670,7 @@ protocol CallServiceObserver: class {
let frontmostViewController = UIApplication . shared . frontmostViewControllerIgnoringAlerts
guard nil != frontmostViewController as ? CallViewController else {
OWSProdError ( OWSAnalyticsEvents . callServiceCallViewCouldNotPresent ( ) , file : #file , function : #function , line : #line )
OWSProdError ( OWSAnalyticsEvents . callServiceCallViewCouldNotPresent ( ) , file : #file , function : #function , line : #line )
owsFail ( " \( TAG ) in \( #function ) Call terminated due to call view presentation delay: \( frontmostViewController . debugDescription ) . " )
self . terminateCall ( )
return