forked from Tadrisino/MathApp_frontend
Android WebView: bridge only on our own https page, external schemes blocked, file access off; payment URL must be http(s)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -40,6 +40,9 @@ class MainActivity : AppCompatActivity() {
|
||||
private var connection: Connection? = null
|
||||
private val webHost: String = Uri.parse(BuildConfig.WEB_URL).host ?: ""
|
||||
|
||||
/** فقط خودِ سایت و فقط با https؛ «http://دامنهی ما» قابلِ دستکاریِ شبکه است و نباید پل داشته باشد. */
|
||||
private fun isOurPage(uri: Uri?): Boolean = uri != null && uri.scheme == "https" && uri.host == webHost
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -48,12 +51,19 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
webView.settings.javaScriptEnabled = true
|
||||
webView.settings.domStorageEnabled = true // توکنِ ورود در localStorage است
|
||||
// WebView فقط آدرسِ وب را میخواند؛ دسترسی به فایل و content:// لازم نیست.
|
||||
webView.settings.allowFileAccess = false
|
||||
webView.settings.allowContentAccess = false
|
||||
webView.webViewClient = object : WebViewClient() {
|
||||
// هر آدرسی بیرونِ دامنهی خودمان در مرورگرِ گوشی باز میشود، نه داخلِ اپ؛ پس پل فقط
|
||||
// در صفحههای خودمان در دسترس است.
|
||||
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
|
||||
if (request.url.host == webHost) return false
|
||||
startActivity(Intent(Intent.ACTION_VIEW, request.url))
|
||||
if (isOurPage(request.url)) return false
|
||||
// فقط http(s) به مرورگرِ گوشی میرود؛ intent:، file: و schemeهای سفارشی بیصدا بسته میشوند
|
||||
// (پیشتر هر آدرسی بیرونِ دامنه به ACTION_VIEW میرفت و صفحه میتوانست اپِ دلخواه باز کند).
|
||||
if (request.url.scheme == "https" || request.url.scheme == "http") {
|
||||
startActivity(Intent(Intent.ACTION_VIEW, request.url))
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -145,14 +155,17 @@ class MainActivity : AppCompatActivity() {
|
||||
@JavascriptInterface
|
||||
fun bazaarPurchase(sku: String, orderId: String) {
|
||||
runOnUiThread {
|
||||
if (Uri.parse(webView.url ?: "").host != webHost) return@runOnUiThread
|
||||
if (!isOurPage(Uri.parse(webView.url ?: ""))) return@runOnUiThread
|
||||
purchase(sku, orderId)
|
||||
}
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun bazaarConsume(purchaseToken: String) {
|
||||
runOnUiThread { consume(purchaseToken) }
|
||||
runOnUiThread {
|
||||
if (!isOurPage(Uri.parse(webView.url ?: ""))) return@runOnUiThread
|
||||
consume(purchaseToken)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -210,6 +210,8 @@ function CheckoutSheet({ plan, bazaar, onClose, onPaid }: { plan: Plan | null; b
|
||||
}
|
||||
}
|
||||
if (!order.paymentUrl) throw new Error('order without paymentUrl');
|
||||
// فقط http(s): یک «javascript:» یا «data:» از پاسخِ API نباید با assign اجرا شود.
|
||||
if (!/^https?:\/\//i.test(order.paymentUrl)) throw new Error('paymentUrl is not http(s)');
|
||||
window.location.assign(order.paymentUrl);
|
||||
} catch (err) {
|
||||
setError(friendlyError(err, 'اتصال به درگاه انجام نشد، دوباره امتحان کن'));
|
||||
|
||||
Reference in New Issue
Block a user