From 9e85b341e39b2c53284705e82bcb95a67fa54405 Mon Sep 17 00:00:00 2001 From: Simon Duchastel Date: Tue, 19 Nov 2024 14:00:28 -0500 Subject: [PATCH] WIP --- .../webview/StripeConnectWebViewContainer.kt | 46 ++---------------- ...StripeConnectWebViewContainerController.kt | 47 +++++++++++++++++++ 2 files changed, 51 insertions(+), 42 deletions(-) diff --git a/connect/src/main/java/com/stripe/android/connect/webview/StripeConnectWebViewContainer.kt b/connect/src/main/java/com/stripe/android/connect/webview/StripeConnectWebViewContainer.kt index ccfd040c157..a383840c120 100644 --- a/connect/src/main/java/com/stripe/android/connect/webview/StripeConnectWebViewContainer.kt +++ b/connect/src/main/java/com/stripe/android/connect/webview/StripeConnectWebViewContainer.kt @@ -90,14 +90,7 @@ internal class StripeConnectWebViewContainerImpl( internal val stripeWebViewClient = StripeConnectWebViewClient() @VisibleForTesting - internal val stripeWebChromeContainer = StripeConnectWebChromeClient( - context = webView?.context ?: throw IllegalStateException("WebView is not initialized"), - embeddedComponentManager = embeddedComponentManager - ?: throw IllegalStateException("EmbeddedComponentManager is not initialized"), - viewScope = { - webView?.findViewTreeLifecycleOwner()?.lifecycleScope ?: throw IllegalStateException("View is not attached") - } - ) + internal val stripeWebChromeContainer = StripeConnectWebChromeClient() private var controller: StripeConnectWebViewContainerController? = null @@ -231,45 +224,14 @@ internal class StripeConnectWebViewContainerImpl( } } - internal class StripeConnectWebChromeClient( - private val context: Context, - private val embeddedComponentManager: EmbeddedComponentManager, - private val viewScope: () -> LifecycleCoroutineScope, - ) : WebChromeClient() { - - private val inProgressRequests: MutableMap = mutableMapOf() - + internal inner class StripeConnectWebChromeClient : WebChromeClient() { override fun onPermissionRequest(request: PermissionRequest) { - // we only care about camera permissions at this time (video/audio) - val permissionsRequested = request.resources.filter { - it in listOf(PermissionRequest.RESOURCE_VIDEO_CAPTURE, PermissionRequest.RESOURCE_AUDIO_CAPTURE) - }.toTypedArray() - if (permissionsRequested.isEmpty()) { - request.deny() // no supported permissions were requested, so reject the request - return - } - - if (checkSelfPermission(context, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { - request.grant(permissionsRequested) - } else { - val job = viewScope().launch { - val isGranted = embeddedComponentManager.requestCameraPermission() - withContext(Dispatchers.Main) { - if (isGranted) { - request.grant(permissionsRequested) - } else { - request.deny() - } - } - inProgressRequests.remove(request) - } - inProgressRequests[request] = job - } + controller?.onPermissionRequest(request) } override fun onPermissionRequestCanceled(request: PermissionRequest?) { if (request == null) return - inProgressRequests.remove(request)?.also { it.cancel() } + controller?.onPermissionRequestCanceled(request) } } diff --git a/connect/src/main/java/com/stripe/android/connect/webview/StripeConnectWebViewContainerController.kt b/connect/src/main/java/com/stripe/android/connect/webview/StripeConnectWebViewContainerController.kt index b6f0c989139..2a022c4e48b 100644 --- a/connect/src/main/java/com/stripe/android/connect/webview/StripeConnectWebViewContainerController.kt +++ b/connect/src/main/java/com/stripe/android/connect/webview/StripeConnectWebViewContainerController.kt @@ -1,6 +1,10 @@ package com.stripe.android.connect.webview +import android.Manifest +import android.content.pm.PackageManager +import android.webkit.PermissionRequest import androidx.annotation.RestrictTo +import androidx.core.content.ContextCompat.checkSelfPermission import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner @@ -9,11 +13,14 @@ import androidx.lifecycle.repeatOnLifecycle import com.stripe.android.connect.EmbeddedComponentManager import com.stripe.android.connect.PrivateBetaConnectSDK import com.stripe.android.connect.StripeEmbeddedComponent +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext @OptIn(PrivateBetaConnectSDK::class) @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) @@ -31,6 +38,8 @@ internal class StripeConnectWebViewContainerController( val stateFlow: StateFlow get() = _stateFlow.asStateFlow() + private val inProgressRequests: MutableMap = mutableMapOf() + /** * Callback to invoke when the view is attached. */ @@ -68,6 +77,44 @@ internal class StripeConnectWebViewContainerController( return embeddedComponentManager.fetchClientSecret() } + /** + * + */ + fun onPermissionRequest(request: PermissionRequest) { + // we only care about camera permissions at this time (video/audio) + val permissionsRequested = request.resources.filter { + it in listOf(PermissionRequest.RESOURCE_VIDEO_CAPTURE, PermissionRequest.RESOURCE_AUDIO_CAPTURE) + }.toTypedArray() + if (permissionsRequested.isEmpty()) { + request.deny() // no supported permissions were requested, so reject the request + return + } + + if (checkSelfPermission(context, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { + request.grant(permissionsRequested) + } else { + val job = viewScope().launch { + val isGranted = embeddedComponentManager.requestCameraPermission() + withContext(Dispatchers.Main) { + if (isGranted) { + request.grant(permissionsRequested) + } else { + request.deny() + } + } + inProgressRequests.remove(request) + } + inProgressRequests[request] = job + } + } + + /** + * + */ + fun onPermissionRequestCanceled(request: PermissionRequest) { + inProgressRequests.remove(request)?.also { it.cancel() } + } + /** * Callback to invoke upon receiving 'pageDidLoad' message. */