From ff0dffd2dcba0e53014dd5f03926d1c717d84d4b Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 11 Dec 2024 23:52:53 +0400 Subject: [PATCH] Updated on 2026-08-14 --- app/build.gradle.kts | 1 - .../com/tangem/core/ui/webview/WebViewExt.kt | 30 ++++++++++ .../disclaimer/impl/ui/DisclaimerScreen.kt | 55 ++++++++----------- .../impl/ui/DisclaimerWebViewClient.kt | 45 --------------- .../ui/AgreementBottomSheetContent.kt | 8 +-- 5 files changed, 55 insertions(+), 84 deletions(-) create mode 100644 core/ui/src/main/java/com/tangem/core/ui/webview/WebViewExt.kt delete mode 100644 features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerWebViewClient.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d63ff6b227..7da64b0215 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -223,7 +223,6 @@ dependencies { implementation(deps.lottie) implementation(deps.compose.accompanist.appCompatTheme) implementation(deps.compose.accompanist.systemUiController) - implementation(deps.compose.accompanist.webView) implementation(deps.xmlShimmer) implementation(deps.viewBindingDelegate) implementation(deps.armadillo) diff --git a/core/ui/src/main/java/com/tangem/core/ui/webview/WebViewExt.kt b/core/ui/src/main/java/com/tangem/core/ui/webview/WebViewExt.kt new file mode 100644 index 0000000000..39ec3d8e8d --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/webview/WebViewExt.kt @@ -0,0 +1,30 @@ +package com.tangem.core.ui.webview + +import android.webkit.WebSettings +import android.webkit.WebView + +/** + * Applies set of settings to prevent base security issues + * +[REDACTED_AUTHOR] + */ +fun WebView.applySafeSettings() { + settings.apply { + // disable to use scripts + javaScriptEnabled = false + + // disable access to files + allowFileAccess = false + + // disable access to content by system content provider + allowContentAccess = false + + // disable to use cached data (scripts, files, etc) + cacheMode = WebSettings.LOAD_NO_CACHE + + // disable to use local storage + domStorageEnabled = false + } + + setDownloadListener(null) +} \ No newline at end of file diff --git a/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerScreen.kt b/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerScreen.kt index f3fe9913c7..1fcc978ace 100644 --- a/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerScreen.kt +++ b/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerScreen.kt @@ -1,7 +1,7 @@ package com.tangem.features.disclaimer.impl.ui -import android.annotation.SuppressLint import android.content.res.Configuration +import android.webkit.WebView import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut @@ -14,7 +14,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource @@ -37,29 +36,22 @@ import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.core.ui.test.TestTags.DISCLAIMER_SCREEN_ACCEPT_BUTTON import com.tangem.core.ui.test.TestTags.DISCLAIMER_SCREEN_CONTAINER +import com.tangem.core.ui.webview.applySafeSettings import com.tangem.features.disclaimer.impl.R import com.tangem.features.disclaimer.impl.entity.DisclaimerUM import com.tangem.features.disclaimer.impl.entity.DummyDisclaimer import com.tangem.features.disclaimer.impl.local.localTermsOfServices import com.tangem.features.pushnotifications.api.utils.getPushPermissionOrNull +import java.nio.charset.StandardCharsets @Composable internal fun DisclaimerScreen(state: DisclaimerUM) { val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() } - val bottomPadding = if (state.isTosAccepted) { - bottomBarHeight + TangemTheme.dimens.size16 - } else { - bottomBarHeight + TangemTheme.dimens.size64 - } - val backgroundColor = if (state.isTosAccepted) TangemTheme.colors.background.primary else TangemColorPalette.Dark6 - val (textColor, iconColor) = if (state.isTosAccepted) { - TangemTheme.colors.text.primary1 to TangemTheme.colors.icon.primary1 - } else { - TangemColorPalette.Light4 to TangemColorPalette.Light4 - } + val bottomPadding = bottomBarHeight + TangemTheme.dimens.size16 + Box( modifier = Modifier - .background(backgroundColor) + .background(TangemTheme.colors.background.primary) .statusBarsPadding() .testTag(DISCLAIMER_SCREEN_CONTAINER), ) { @@ -75,14 +67,15 @@ internal fun DisclaimerScreen(state: DisclaimerUM) { onIconClicked = state.popBack, ).takeIf { state.isTosAccepted }, titleAlignment = Alignment.CenterHorizontally, - textColor = textColor, - iconTint = iconColor, ) - DisclaimerContent(state.url, state.isTosAccepted) + DisclaimerContent(state.url) } if (!state.isTosAccepted) { - BottomFade(Modifier.align(Alignment.BottomCenter), backgroundColor = backgroundColor) + BottomFade( + modifier = Modifier.align(Alignment.BottomCenter), + backgroundColor = TangemTheme.colors.background.primary, + ) DisclaimerButton(state.onAccept) } else { NavigationBar3ButtonsScrim() @@ -90,14 +83,14 @@ internal fun DisclaimerScreen(state: DisclaimerUM) { } } -@SuppressLint("SetJavaScriptEnabled") @Composable -private fun DisclaimerContent(url: String, isTosAccepted: Boolean) { - val backgroundColor = if (isTosAccepted) TangemTheme.colors.background.primary else TangemColorPalette.Dark6 - +private fun DisclaimerContent(url: String) { val webViewStateUrl = rememberWebViewState(url) - val webViewStateData = - rememberWebViewStateWithHTMLData(data = localTermsOfServices, mimeType = "text/html", encoding = "UTF-8") + val webViewStateData = rememberWebViewStateWithHTMLData( + data = localTermsOfServices, + mimeType = "text/html", + encoding = StandardCharsets.UTF_8.name(), + ) val webViewState by remember { derivedStateOf { @@ -113,12 +106,10 @@ private fun DisclaimerContent(url: String, isTosAccepted: Boolean) { WebView( state = webViewState, captureBackPresses = false, - onCreated = { - it.settings.javaScriptEnabled = !isTosAccepted - it.setBackgroundColor(backgroundColor.toArgb()) - }, - client = remember { DisclaimerWebViewClient() }, - modifier = Modifier.fillMaxSize(), + onCreated = WebView::applySafeSettings, + modifier = Modifier + .fillMaxSize() + .background(TangemTheme.colors.background.primary), ) AnimatedVisibility( @@ -128,12 +119,12 @@ private fun DisclaimerContent(url: String, isTosAccepted: Boolean) { exit = fadeOut(), modifier = Modifier .fillMaxSize() - .background(backgroundColor), + .background(TangemTheme.colors.background.primary), ) { Box( modifier = Modifier .fillMaxSize() - .background(backgroundColor), + .background(TangemTheme.colors.background.primary), ) { CircularProgressIndicator( color = TangemTheme.colors.icon.informative, diff --git a/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerWebViewClient.kt b/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerWebViewClient.kt deleted file mode 100644 index c3046d0855..0000000000 --- a/features/disclaimer/impl/src/main/java/com/tangem/features/disclaimer/impl/ui/DisclaimerWebViewClient.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.tangem.features.disclaimer.impl.ui - -import android.graphics.Bitmap -import android.webkit.WebView -import com.google.accompanist.web.AccompanistWebViewClient - -internal enum class ProgressState { - Loading, - Done, - Error, -} - -/** - * Workaround to display web view with ToS only in dark theme - */ -private fun WebView.injectCSS() { - val code = "javascript:(function() {" + - "var node = document.createElement('style');" + - "node.type = 'text/css';" + - " node.innerHTML = 'body, label,th,p,a, td, tr,li,ul,span,table,h1,h2,h3,h4,h5,h6,h7,div,small {" + - " color: #C9C9C9;" + - "background-color: #1E1E1E;" + - " } ';" + - " document.head.appendChild(node);})();" - - evaluateJavascript(code, null) -} - -internal class DisclaimerWebViewClient : AccompanistWebViewClient() { - - override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { - view?.injectCSS() - super.onPageStarted(view, url, favicon) - } - - override fun onPageCommitVisible(view: WebView?, url: String?) { - view?.injectCSS() - super.onPageCommitVisible(view, url) - } - - override fun onPageFinished(view: WebView?, url: String?) { - view?.injectCSS() - super.onPageFinished(view, url) - } -} \ No newline at end of file diff --git a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/AgreementBottomSheetContent.kt b/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/AgreementBottomSheetContent.kt index 66be1782f1..b1245ee718 100644 --- a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/AgreementBottomSheetContent.kt +++ b/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/AgreementBottomSheetContent.kt @@ -20,6 +20,7 @@ import com.google.accompanist.web.rememberWebViewState import com.tangem.core.ui.components.appbar.TangemTopAppBar import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.core.ui.webview.applySafeSettings import com.tangem.feature.referral.presentation.R /** @@ -50,12 +51,7 @@ private fun AgreementHtmlView(url: String) { modifier = Modifier.background(TangemTheme.colors.background.primary), captureBackPresses = false, onCreated = { - if (!isInPreviewMode) { - it.settings.apply { - javaScriptEnabled = false - allowFileAccess = false - } - } + if (!isInPreviewMode) it.applySafeSettings() }, ) }