diff --git a/app/src/main/java/com/duckduckgo/app/browser/webview/MaliciousSiteBlockerWebViewIntegration.kt b/app/src/main/java/com/duckduckgo/app/browser/webview/MaliciousSiteBlockerWebViewIntegration.kt index ab00b5d78f2a..46e4cb77bada 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/webview/MaliciousSiteBlockerWebViewIntegration.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/webview/MaliciousSiteBlockerWebViewIntegration.kt @@ -32,6 +32,7 @@ import com.duckduckgo.privacy.config.api.PrivacyConfigCallbackPlugin import com.squareup.anvil.annotations.ContributesBinding import com.squareup.anvil.annotations.ContributesMultibinding import java.net.URLDecoder +import java.util.concurrent.atomic.AtomicInteger import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -68,6 +69,7 @@ class RealMaliciousSiteBlockerWebViewIntegration @Inject constructor( @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) val processedUrls = mutableListOf() private var isFeatureEnabled = false + private var currentCheckId = AtomicInteger(0) init { if (isMainProcess) { @@ -109,13 +111,8 @@ class RealMaliciousSiteBlockerWebViewIntegration @Inject constructor( return null } - if (request.isForMainFrame) { - if (maliciousSiteProtection.isMalicious(decodedUrl.toUri(), confirmationCallback) == MALICIOUS) { - return WebResourceResponse(null, null, null) - } - processedUrls.add(decodedUrl) - } else if (isForIframe(request) && documentUri?.host == request.requestHeaders["Referer"]?.toUri()?.host) { - if (maliciousSiteProtection.isMalicious(decodedUrl.toUri(), confirmationCallback) == MALICIOUS) { + if (request.isForMainFrame || (isForIframe(request) && documentUri?.host == request.requestHeaders["Referer"]?.toUri()?.host)) { + if (checkMaliciousUrl(decodedUrl, confirmationCallback)) { return WebResourceResponse(null, null, null) } processedUrls.add(decodedUrl) @@ -142,7 +139,7 @@ class RealMaliciousSiteBlockerWebViewIntegration @Inject constructor( // iframes always go through the shouldIntercept method, so we only need to check the main frame here if (isForMainFrame) { - if (maliciousSiteProtection.isMalicious(decodedUrl.toUri(), confirmationCallback) == MALICIOUS) { + if (checkMaliciousUrl(decodedUrl, confirmationCallback)) { return@runBlocking true } processedUrls.add(decodedUrl) @@ -151,6 +148,19 @@ class RealMaliciousSiteBlockerWebViewIntegration @Inject constructor( } } + private suspend fun checkMaliciousUrl( + url: String, + confirmationCallback: (isMalicious: Boolean) -> Unit, + ): Boolean { + val checkId = currentCheckId.incrementAndGet() + return maliciousSiteProtection.isMalicious(url.toUri()) { isMalicious -> + // TODO: Add tests for this + if (checkId == currentCheckId.get()) { + confirmationCallback(isMalicious) + } + } == MALICIOUS + } + private fun isForIframe(request: WebResourceRequest) = request.requestHeaders["Sec-Fetch-Dest"] == "iframe" || request.url.path?.contains("/embed/") == true || request.url.path?.contains("/iframe/") == true ||