Coverage Summary for Class: WebViewPermissionRequesterImpl (cloud.mindbox.mobile_sdk.inapp.presentation.view)

Class Method, % Branch, % Line, % Instruction, %
WebViewPermissionRequesterImpl 100% (7/7) 90% (9/10) 100% (31/31) 100% (120/120)
WebViewPermissionRequesterImpl$1 0% (0/1) 0% (0/1) 0% (0/2)
WebViewPermissionRequesterImpl$requestPermission$1
WebViewPermissionRequesterImpl$WhenMappings
Total 87.5% (7/8) 90% (9/10) 96.9% (31/32) 98.4% (120/122)


 package cloud.mindbox.mobile_sdk.inapp.presentation.view
 
 import android.Manifest
 import android.annotation.SuppressLint
 import android.app.Activity
 import android.content.Context
 import android.content.Intent
 import android.os.Build
 import cloud.mindbox.mobile_sdk.Mindbox
 import cloud.mindbox.mobile_sdk.inapp.data.managers.PermissionManagerImpl
 import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.PermissionManager
 import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.PermissionStatus
 import cloud.mindbox.mobile_sdk.inapp.presentation.actions.PushActivationActivity
 import cloud.mindbox.mobile_sdk.inapp.presentation.actions.RuntimePermissionRequestBridge
 import com.google.gson.annotations.SerializedName
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.withContext
 
 internal const val PERMISSION_PAYLOAD_TYPE_FIELD_NAME = "type"
 
 internal interface WebViewPermissionRequester {
     suspend fun requestPermission(activity: Activity, permissionType: PermissionType): PermissionActionResponse
 }
 
 internal enum class PermissionType(val value: String) {
     PUSH_NOTIFICATIONS("pushNotifications")
 }
 
 internal data class PermissionActionResponse(
     @SerializedName("result")
     val result: PermissionRequestStatus,
     @SerializedName("dialogShown")
     val dialogShown: Boolean,
     @SerializedName("details")
     val details: PermissionActionDetails,
 )
 
 internal data class PermissionActionDetails(
     @SerializedName("required")
     val required: Boolean,
     @SerializedName("shouldShowRequestPermissionRationale")
     val shouldShowRequestPermissionRationale: Boolean? = null,
 )
 
 internal enum class PermissionRequestStatus(val value: String) {
     @SerializedName("granted")
     GRANTED("granted"),
 
     @SerializedName("denied")
     DENIED("denied")
 }
 
 @SuppressLint("InlinedApi")
 internal class WebViewPermissionRequesterImpl(
     private val context: Context,
     private val pushPermissionLauncher: PushPermissionLauncher = PushPermissionLauncherImpl(),
     private val permissionManager: PermissionManager = PermissionManagerImpl(context),
     private val sdkIntProvider: () -> Int = { Build.VERSION.SDK_INT },
 ) : WebViewPermissionRequester {
 
     override suspend fun requestPermission(
         activity: Activity,
         permissionType: PermissionType
     ): PermissionActionResponse {
         val currentStatus: PermissionStatus = getPermissionStatus(permissionType)
         if (isGrantedStatus(currentStatus)) {
             return createPermissionActionResponse(
                 result = PermissionRequestStatus.GRANTED,
                 dialogShown = false
             )
         }
         if (!isPermissionRequired()) {
             return createPermissionActionResponse(
                 result = PermissionRequestStatus.DENIED,
                 dialogShown = false
             )
         }
 
         val permissionResult: PushPermissionRequestResult = pushPermissionLauncher.requestPermission(activity = activity)
         return createPermissionActionResponse(
             result = permissionResult.status,
             dialogShown = permissionResult.dialogShown,
             shouldShowRequestPermissionRationale = permissionResult.shouldShowRequestPermissionRationale
         )
     }
 
     private fun getPermissionStatus(permissionType: PermissionType): PermissionStatus {
         return when (permissionType) {
             PermissionType.PUSH_NOTIFICATIONS -> permissionManager.getNotificationPermissionStatus()
         }
     }
 
     private fun isGrantedStatus(permissionStatus: PermissionStatus): Boolean {
         return permissionStatus == PermissionStatus.GRANTED || permissionStatus == PermissionStatus.LIMITED
     }
 
     private fun isPermissionRequired(): Boolean = sdkIntProvider() >= Build.VERSION_CODES.TIRAMISU
 
     private fun createPermissionActionResponse(
         result: PermissionRequestStatus,
         dialogShown: Boolean,
         shouldShowRequestPermissionRationale: Boolean? = null
     ): PermissionActionResponse {
         val isPermissionRequired: Boolean = isPermissionRequired()
         return PermissionActionResponse(
             result = result,
             dialogShown = dialogShown,
             details = PermissionActionDetails(
                 required = isPermissionRequired,
                 shouldShowRequestPermissionRationale = shouldShowRequestPermissionRationale
             )
         )
     }
 }
 
 internal interface PushPermissionLauncher {
     suspend fun requestPermission(activity: Activity): PushPermissionRequestResult
 }
 
 internal data class PushPermissionRequestResult(
     val status: PermissionRequestStatus,
     val shouldShowRequestPermissionRationale: Boolean,
     val dialogShown: Boolean,
 )
 
 @SuppressLint("InlinedApi")
 internal class PushPermissionLauncherImpl(
     private val sdkIntProvider: () -> Int = { Build.VERSION.SDK_INT }
 ) : PushPermissionLauncher {
     private val notificationPermission: String = Manifest.permission.POST_NOTIFICATIONS
 
     override suspend fun requestPermission(activity: Activity): PushPermissionRequestResult {
         if (sdkIntProvider() < Build.VERSION_CODES.TIRAMISU) {
             return PushPermissionRequestResult(
                 status = PermissionRequestStatus.DENIED,
                 shouldShowRequestPermissionRationale = false,
                 dialogShown = false
             )
         }
         val requestId: String = Mindbox.generateRandomUuid()
         val deferredResult = RuntimePermissionRequestBridge.register(requestId)
         withContext(Dispatchers.Main.immediate) {
             activity.startActivity(
                 Intent(activity, PushActivationActivity::class.java).apply {
                     putExtra(PushActivationActivity.EXTRA_REQUEST_ID, requestId)
                     putExtra(PushActivationActivity.EXTRA_ROUTE_TO_SETTINGS, false)
                 }
             )
         }
         val (isGranted, dialogShown) = deferredResult.await()
         val shouldShowRationale: Boolean = withContext(Dispatchers.Main.immediate) {
             activity.shouldShowRequestPermissionRationale(notificationPermission)
         }
         return PushPermissionRequestResult(
             status = if (isGranted) PermissionRequestStatus.GRANTED else PermissionRequestStatus.DENIED,
             shouldShowRequestPermissionRationale = shouldShowRationale,
             dialogShown = dialogShown
         )
     }
 }