Skip to content

Commit

Permalink
Eliminate preview for tabs showing malicious site warning and add err…
Browse files Browse the repository at this point in the history
…or page pixels (#5602)

Task/Issue URL:
https://app.asana.com/0/1201870266890790/1209289574297311/f

### Description
Don't show preview of blocked page in tab switcher when malicious site
warning has been triggered

### Steps to test this PR

_Block tab previews for warning page_
- [ ] Open new tab with
https://privacy-test-pages.site/security/badware/malware.html
- [ ] When warning shows, tap to show all tabs
- [ ] Check that there is no bitmap preview for that tab
  • Loading branch information
laghee authored Feb 9, 2025
1 parent 9fae324 commit fd1bc63
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -874,7 +874,9 @@ class BrowserTabFragment :
object : DefaultLifecycleObserver {
override fun onStop(owner: LifecycleOwner) {
if (isVisible) {
updateOrDeleteWebViewPreview()
if (viewModel.browserViewState.value?.maliciousSiteDetected != true) {
updateOrDeleteWebViewPreview()
}
}
}
},
Expand Down Expand Up @@ -1400,6 +1402,10 @@ class BrowserTabFragment :
maliciousWarningView.bind(feed) { action ->
viewModel.onMaliciousSiteUserAction(action, url, feed, isActiveCustomTab())
}
viewModel.deleteTabPreview(tabId)
lifecycleScope.launch(dispatchers.main()) {
viewModel.updateTabTitle(tabId, newTitle = SITE_SECURITY_WARNING)
}
maliciousWarningView.show()
binding.focusDummy.requestFocus()
}
Expand Down Expand Up @@ -3654,6 +3660,8 @@ class BrowserTabFragment :

private const val AUTOCOMPLETE_PADDING_DP = 6

private const val SITE_SECURITY_WARNING = "Warning: Security Risk"

fun newInstance(
tabId: String,
query: String? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1882,6 +1882,8 @@ class BrowserTabViewModel @Inject constructor(
) {
when (action) {
LeaveSite -> {
val params = mapOf(CATEGORY_KEY to feed.name)
pixel.fire(AppPixelName.MALICIOUS_SITE_PROTECTION_VISIT_SITE, params)
if (activeCustomTab) {
command.postValue(CloseCustomTab)
} else {
Expand Down Expand Up @@ -3197,13 +3199,14 @@ class BrowserTabViewModel @Inject constructor(
command.postValue(WebViewError(errorType, url))
}

override fun onReceivedMaliciousSiteWarning(url: Uri, feed: Feed, exempted: Boolean) {
// TODO (cbarreiro): Fire pixel
override fun onReceivedMaliciousSiteWarning(url: Uri, feed: Feed, exempted: Boolean, clientSideHit: Boolean) {
site?.maliciousSiteStatus = when (feed) {
MALWARE -> MaliciousSiteStatus.MALWARE
PHISHING -> MaliciousSiteStatus.PHISHING
}
if (!exempted) {
val params = mapOf(CATEGORY_KEY to feed.name, CLIENT_SIDE_HIT_KEY to clientSideHit.toString())
pixel.fire(AppPixelName.MALICIOUS_SITE_PROTECTION_ERROR_SHOWN, params)
loadingViewState.postValue(
currentLoadingViewState().copy(isLoading = false, progress = 100, url = url.toString()),
)
Expand All @@ -3218,6 +3221,13 @@ class BrowserTabViewModel @Inject constructor(
}
}

suspend fun updateTabTitle(tabId: String, newTitle: String) {
getSite()?.let { site ->
site.title = newTitle
tabRepository.update(tabId, site)
}
}

override fun recordErrorCode(
error: String,
url: String,
Expand Down Expand Up @@ -3822,6 +3832,9 @@ class BrowserTabViewModel @Inject constructor(
private const val HTTP_STATUS_CODE_CLIENT_ERROR_PREFIX = 4 // 4xx, client error status code prefix
private const val HTTP_STATUS_CODE_SERVER_ERROR_PREFIX = 5 // 5xx, server error status code prefix

private const val CATEGORY_KEY = "category"
private const val CLIENT_SIDE_HIT_KEY = "clientSideHit"

// https://www.iso.org/iso-3166-country-codes.html
private val PRINT_LETTER_FORMAT_COUNTRIES_ISO3166_2 = setOf(
Locale.US.country,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ interface WebViewClientListener {
fun linkOpenedInNewTab(): Boolean
fun isActiveTab(): Boolean
fun onReceivedError(errorType: WebViewErrorResponse, url: String)
fun onReceivedMaliciousSiteWarning(url: Uri, feed: Feed, exempted: Boolean)
fun onReceivedMaliciousSiteWarning(url: Uri, feed: Feed, exempted: Boolean, clientSideHit: Boolean)
fun recordErrorCode(error: String, url: String)
fun recordHttpErrorCode(statusCode: Int, url: String)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ class WebViewRequestInterceptor(
when (result) {
WaitForConfirmation, Safe -> return false
is MaliciousSite -> {
handleSiteBlocked(webViewClientListener, url, result.feed, result.exempted)
handleSiteBlocked(webViewClientListener, url, result.feed, result.exempted, clientSideHit = true)
return !result.exempted
}
}
Expand All @@ -220,12 +220,12 @@ class WebViewRequestInterceptor(
/*
* If the site is exempted, we'll never get here, as we won't call isMalicious
*/
handleSiteBlocked(webViewClientListener, url, isMalicious.feed, false)
handleSiteBlocked(webViewClientListener, url, isMalicious.feed, exempted = false, clientSideHit = false)
}
}

private fun handleSiteBlocked(webViewClientListener: WebViewClientListener?, url: Uri?, feed: Feed, exempted: Boolean) {
url?.let { webViewClientListener?.onReceivedMaliciousSiteWarning(it, feed, exempted) }
private fun handleSiteBlocked(webViewClientListener: WebViewClientListener?, url: Uri?, feed: Feed, exempted: Boolean, clientSideHit: Boolean) {
url?.let { webViewClientListener?.onReceivedMaliciousSiteWarning(it, feed, exempted, clientSideHit) }
}

override fun addExemptedMaliciousSite(url: Uri, feed: Feed) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ object PixelInterceptorPixelsRequiringDataCleaning : PixelParamRemovalPlugin {
SITE_NOT_WORKING_WEBSITE_BROKEN.pixelName to PixelParameter.removeAtb(),
AppPixelName.APP_VERSION_AT_SEARCH_TIME.pixelName to PixelParameter.removeAll(),
AppPixelName.MALICIOUS_SITE_PROTECTION_SETTING_TOGGLED.pixelName to PixelParameter.removeAtb(),
AppPixelName.MALICIOUS_SITE_PROTECTION_VISIT_SITE.pixelName to PixelParameter.removeAtb(),
AppPixelName.MALICIOUS_SITE_PROTECTION_ERROR_SHOWN.pixelName to PixelParameter.removeAtb(),
AppPixelName.SET_AS_DEFAULT_PROMPT_IMPRESSION.pixelName to PixelParameter.removeAll(),
AppPixelName.SET_AS_DEFAULT_PROMPT_CLICK.pixelName to PixelParameter.removeAll(),
AppPixelName.SET_AS_DEFAULT_PROMPT_DISMISSED.pixelName to PixelParameter.removeAll(),
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/com/duckduckgo/app/pixels/AppPixelName.kt
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,8 @@ enum class AppPixelName(override val pixelName: String) : Pixel.PixelName {
DUCK_PLAYER_SETTING_ALWAYS_DUCK_PLAYER("duckplayer_setting_always_duck-player"),

MALICIOUS_SITE_PROTECTION_SETTING_TOGGLED("m_malicious-site-protection_feature-toggled"),
MALICIOUS_SITE_PROTECTION_VISIT_SITE("m_malicious-site-protection_visit-site"),
MALICIOUS_SITE_PROTECTION_ERROR_SHOWN("m_malicious-site-protection_error-page-shown"),

ADD_BOOKMARK_CONFIRM_EDITED("m_add_bookmark_confirm_edit"),

Expand Down

0 comments on commit fd1bc63

Please sign in to comment.