@@ -7,18 +7,24 @@ package org.microg.vending.billing.ui
77
88import android.accounts.Account
99import android.accounts.AccountManager
10+ import android.graphics.Bitmap
1011import android.net.Uri
1112import android.os.Build.VERSION.SDK_INT
13+ import android.os.Message
1214import android.util.Log
1315import android.view.View
1416import android.webkit.CookieManager
17+ import android.webkit.WebChromeClient
1518import android.webkit.WebResourceRequest
1619import android.webkit.WebSettings
1720import android.webkit.WebView
21+ import android.widget.ProgressBar
22+ import android.widget.RelativeLayout
1823import androidx.activity.ComponentActivity
1924import androidx.lifecycle.lifecycleScope
2025import androidx.webkit.WebResourceErrorCompat
2126import androidx.webkit.WebViewClientCompat
27+ import com.google.android.material.bottomsheet.BottomSheetDialog
2228import kotlinx.coroutines.Dispatchers
2329import kotlinx.coroutines.launch
2430import org.microg.gms.profile.Build
@@ -32,8 +38,9 @@ class WebViewHelper(
3238 private val webView : WebView ,
3339 private val allowedPrefixes : Set <String > = emptySet()
3440) {
35- fun openWebView (url : String , account : Account ? ) {
36- prepareWebViewSettings(webView.settings)
41+ fun openWebView (url : String , account : Account ? , webAction : WebViewAction ) {
42+ prepareWebViewSettings(webView.settings, webAction == WebViewAction .ADD_PAYMENT_METHOD )
43+ webView.webChromeClient = PayWebChromeClient (webAction)
3744 webView.webViewClient = object : WebViewClientCompat () {
3845 override fun onReceivedError (view : WebView , request : WebResourceRequest , error : WebResourceErrorCompat ) {
3946 Log .e(TAG , " Error loading: $error " )
@@ -113,9 +120,9 @@ class WebViewHelper(
113120 }
114121 }
115122
116- private fun prepareWebViewSettings (settings : WebSettings ) {
123+ private fun prepareWebViewSettings (settings : WebSettings , enableMultiWindow : Boolean = false ) {
117124 settings.javaScriptEnabled = true
118- settings.setSupportMultipleWindows(false )
125+ settings.setSupportMultipleWindows(enableMultiWindow )
119126 settings.allowFileAccess = false
120127 settings.databaseEnabled = false
121128 settings.setNeedInitialFocus(false )
@@ -124,4 +131,65 @@ class WebViewHelper(
124131 settings.javaScriptCanOpenWindowsAutomatically = false
125132 settings.userAgentString = Build .generateWebViewUserAgentString(settings.userAgentString)
126133 }
134+
135+ private class PayWebChromeClient (val webAction : WebViewAction ) : WebChromeClient() {
136+
137+ override fun onCreateWindow (view : WebView ? , isDialog : Boolean , isUserGesture : Boolean , resultMsg : Message ? ): Boolean {
138+ Log .d(TAG , " onCreateWindow: isDialog:$isDialog isUserGesture:$isUserGesture resultMsg: ${resultMsg.toString()} " )
139+ if (webAction != WebViewAction .ADD_PAYMENT_METHOD ) {
140+ return super .onCreateWindow(view, isDialog, isUserGesture, resultMsg)
141+ }
142+ // Add third-party payment methods, such as PayPal/GrabPay/Alipay.
143+ // WebView needs to support multi-window mode, and the child view will call the js method registered by the parent view
144+ // to refresh the page and close it by itself.
145+ var bottomSheetDialog: BottomSheetDialog ? = null
146+ val parentContext = view!! .context
147+ val subWebView = WebView (parentContext).apply {
148+ settings.apply {
149+ javaScriptEnabled = true
150+ domStorageEnabled = true
151+ }
152+ webViewClient = object : WebViewClientCompat () {
153+ override fun onPageStarted (view : WebView ? , url : String? , favicon : Bitmap ? ) {
154+ super .onPageStarted(view, url, favicon)
155+ Log .d(TAG , " sub_window starts loading: $url " )
156+ }
157+
158+ override fun onPageFinished (view : WebView ? , url : String? ) {
159+ super .onPageFinished(view, url)
160+ Log .d(TAG , " sub_window loaded : $url " )
161+ visibility = View .VISIBLE
162+ }
163+ }
164+ webChromeClient = object : WebChromeClient () {
165+ override fun onCloseWindow (window : WebView ? ) {
166+ Log .d(TAG , " sub_window closed" )
167+ bottomSheetDialog?.dismiss()
168+ }
169+ }
170+ layoutParams = RelativeLayout .LayoutParams (RelativeLayout .LayoutParams .MATCH_PARENT , RelativeLayout .LayoutParams .MATCH_PARENT )
171+ visibility = View .INVISIBLE
172+ }
173+ bottomSheetDialog = BottomSheetDialog (parentContext).apply {
174+ setOnDismissListener { subWebView.destroy() }
175+ }
176+ val layout = RelativeLayout (parentContext)
177+ layout.addView(ProgressBar (parentContext).apply {
178+ layoutParams = RelativeLayout .LayoutParams (
179+ RelativeLayout .LayoutParams .WRAP_CONTENT ,
180+ RelativeLayout .LayoutParams .WRAP_CONTENT
181+ ).apply {
182+ addRule(RelativeLayout .CENTER_HORIZONTAL )
183+ addRule(RelativeLayout .CENTER_VERTICAL )
184+ }
185+ isIndeterminate = true
186+ })
187+ bottomSheetDialog.setContentView(layout.apply { addView(subWebView) })
188+ bottomSheetDialog.show()
189+
190+ (resultMsg?.obj as ? WebView .WebViewTransport )?.webView = subWebView
191+ resultMsg?.sendToTarget()
192+ return true
193+ }
194+ }
127195}
0 commit comments