Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Vending: Expand payment methods
  • Loading branch information
DaVinci9196 committed Apr 29, 2025
commit bd0f197c2e5074da23e8a90a6708f492ab7877fe
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class PlayWebViewActivity : ComponentActivity() {
}
layout.addView(webView)
setContentView(layout)
WebViewHelper(this, webView, ALLOWED_WEB_PREFIXES).openWebView(openUrl, account)
WebViewHelper(this, webView, ALLOWED_WEB_PREFIXES).openWebView(openUrl, account, action)
setResult(RESULT_OK)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,24 @@ package org.microg.vending.billing.ui

import android.accounts.Account
import android.accounts.AccountManager
import android.graphics.Bitmap
import android.net.Uri
import android.os.Build.VERSION.SDK_INT
import android.os.Message
import android.util.Log
import android.view.View
import android.webkit.CookieManager
import android.webkit.WebChromeClient
import android.webkit.WebResourceRequest
import android.webkit.WebSettings
import android.webkit.WebView
import android.widget.ProgressBar
import android.widget.RelativeLayout
import androidx.activity.ComponentActivity
import androidx.lifecycle.lifecycleScope
import androidx.webkit.WebResourceErrorCompat
import androidx.webkit.WebViewClientCompat
import com.google.android.material.bottomsheet.BottomSheetDialog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.microg.gms.profile.Build
Expand All @@ -32,8 +38,9 @@ class WebViewHelper(
private val webView: WebView,
private val allowedPrefixes: Set<String> = emptySet()
) {
fun openWebView(url: String, account: Account?) {
prepareWebViewSettings(webView.settings)
fun openWebView(url: String, account: Account?, webAction: WebViewAction) {
prepareWebViewSettings(webView.settings, webAction == WebViewAction.ADD_PAYMENT_METHOD)
webView.webChromeClient = PayWebChromeClient(webAction)
webView.webViewClient = object : WebViewClientCompat() {
override fun onReceivedError(view: WebView, request: WebResourceRequest, error: WebResourceErrorCompat) {
Log.e(TAG, "Error loading: $error")
Expand Down Expand Up @@ -113,9 +120,9 @@ class WebViewHelper(
}
}

private fun prepareWebViewSettings(settings: WebSettings) {
private fun prepareWebViewSettings(settings: WebSettings, enableMultiWindow: Boolean = false) {
settings.javaScriptEnabled = true
settings.setSupportMultipleWindows(false)
settings.setSupportMultipleWindows(enableMultiWindow)
settings.allowFileAccess = false
settings.databaseEnabled = false
settings.setNeedInitialFocus(false)
Expand All @@ -124,4 +131,65 @@ class WebViewHelper(
settings.javaScriptCanOpenWindowsAutomatically = false
settings.userAgentString = Build.generateWebViewUserAgentString(settings.userAgentString)
}

private class PayWebChromeClient(val webAction: WebViewAction) : WebChromeClient() {

override fun onCreateWindow(view: WebView?, isDialog: Boolean, isUserGesture: Boolean, resultMsg: Message?): Boolean {
Log.d(TAG, "onCreateWindow: isDialog:$isDialog isUserGesture:$isUserGesture resultMsg: ${resultMsg.toString()}")
if (webAction != WebViewAction.ADD_PAYMENT_METHOD) {
return super.onCreateWindow(view, isDialog, isUserGesture, resultMsg)
}
// Add third-party payment methods, such as PayPal/GrabPay/Alipay.
// WebView needs to support multi-window mode, and the child view will call the js method registered by the parent view
// to refresh the page and close it by itself.
var bottomSheetDialog: BottomSheetDialog? = null
val parentContext = view!!.context
val subWebView = WebView(parentContext).apply {
settings.apply {
javaScriptEnabled = true
domStorageEnabled = true
}
webViewClient = object : WebViewClientCompat() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
Log.d(TAG, "sub_window starts loading: $url")
}

override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
Log.d(TAG, "sub_window loaded : $url")
visibility = View.VISIBLE
}
}
webChromeClient = object : WebChromeClient() {
override fun onCloseWindow(window: WebView?) {
Log.d(TAG, "sub_window closed")
bottomSheetDialog?.dismiss()
}
}
layoutParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT)
visibility = View.INVISIBLE
}
bottomSheetDialog = BottomSheetDialog(parentContext).apply {
setOnDismissListener { subWebView.destroy() }
}
val layout = RelativeLayout(parentContext)
layout.addView(ProgressBar(parentContext).apply {
layoutParams = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
).apply {
addRule(RelativeLayout.CENTER_HORIZONTAL)
addRule(RelativeLayout.CENTER_VERTICAL)
}
isIndeterminate = true
})
bottomSheetDialog.setContentView(layout.apply { addView(subWebView) })
bottomSheetDialog.show()

(resultMsg?.obj as? WebView.WebViewTransport)?.webView = subWebView
resultMsg?.sendToTarget()
return true
}
}
}