From 05e871dd0cba6037210cff6d7bbec94cad24af41 Mon Sep 17 00:00:00 2001 From: Artur Dryomov Date: Wed, 30 Oct 2019 21:08:45 +0300 Subject: [PATCH] No issue: Refactor errors to risk level conversion. (#5710) --- .../mozilla/fenix/AppRequestInterceptor.kt | 96 +++++++-------- .../fenix/AppRequestInterceptorTest.kt | 112 ++++++++++++++++++ 2 files changed, 152 insertions(+), 56 deletions(-) create mode 100644 app/src/test/java/org/mozilla/fenix/AppRequestInterceptorTest.kt diff --git a/app/src/main/java/org/mozilla/fenix/AppRequestInterceptor.kt b/app/src/main/java/org/mozilla/fenix/AppRequestInterceptor.kt index 8771e0a3e..4cb9e90c9 100644 --- a/app/src/main/java/org/mozilla/fenix/AppRequestInterceptor.kt +++ b/app/src/main/java/org/mozilla/fenix/AppRequestInterceptor.kt @@ -5,6 +5,7 @@ package org.mozilla.fenix import android.content.Context +import androidx.annotation.RawRes import mozilla.components.browser.errorpages.ErrorPages import mozilla.components.browser.errorpages.ErrorType import mozilla.components.concept.engine.EngineSession @@ -48,71 +49,54 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor { uri: String? ): RequestInterceptor.ErrorResponse? { val riskLevel = getRiskLevel(errorType) - val htmlResource = getPageForRiskLevel(riskLevel) - val cssResource = getStyleForRiskLevel(riskLevel) context.components.analytics.metrics.track(Event.ErrorPageVisited(errorType)) + return RequestInterceptor.ErrorResponse( - ErrorPages - .createErrorPage(context, errorType, uri = uri, htmlResource = htmlResource, cssResource = cssResource) + ErrorPages.createErrorPage( + context, + errorType, + uri = uri, + htmlResource = riskLevel.htmlRes, + cssResource = riskLevel.cssRes + ) ) } - private fun getPageForRiskLevel(riskLevel: RiskLevel): Int { - return when (riskLevel) { - RiskLevel.Low -> R.raw.low_risk_error_pages - RiskLevel.Medium -> R.raw.medium_and_high_risk_error_pages - RiskLevel.High -> R.raw.medium_and_high_risk_error_pages - } - } - - private fun getStyleForRiskLevel(riskLevel: RiskLevel): Int { - return when (riskLevel) { - RiskLevel.Low -> R.raw.low_and_medium_risk_error_style - RiskLevel.Medium -> R.raw.low_and_medium_risk_error_style - RiskLevel.High -> R.raw.high_risk_error_style - } - } + private fun getRiskLevel(errorType: ErrorType): RiskLevel = when (errorType) { + ErrorType.UNKNOWN, + ErrorType.ERROR_NET_INTERRUPT, + ErrorType.ERROR_NET_TIMEOUT, + ErrorType.ERROR_CONNECTION_REFUSED, + ErrorType.ERROR_UNKNOWN_SOCKET_TYPE, + ErrorType.ERROR_REDIRECT_LOOP, + ErrorType.ERROR_OFFLINE, + ErrorType.ERROR_NET_RESET, + ErrorType.ERROR_UNSAFE_CONTENT_TYPE, + ErrorType.ERROR_CORRUPTED_CONTENT, + ErrorType.ERROR_CONTENT_CRASHED, + ErrorType.ERROR_INVALID_CONTENT_ENCODING, + ErrorType.ERROR_UNKNOWN_HOST, + ErrorType.ERROR_MALFORMED_URI, + ErrorType.ERROR_FILE_NOT_FOUND, + ErrorType.ERROR_FILE_ACCESS_DENIED, + ErrorType.ERROR_PROXY_CONNECTION_REFUSED, + ErrorType.ERROR_UNKNOWN_PROXY_HOST, + ErrorType.ERROR_UNKNOWN_PROTOCOL -> RiskLevel.Low - private fun getRiskLevel(errorType: ErrorType): RiskLevel { - return when (errorType) { - // Low risk errors - ErrorType.UNKNOWN -> RiskLevel.Low - ErrorType.ERROR_NET_INTERRUPT -> RiskLevel.Low - ErrorType.ERROR_NET_TIMEOUT -> RiskLevel.Low - ErrorType.ERROR_CONNECTION_REFUSED -> RiskLevel.Low - ErrorType.ERROR_UNKNOWN_SOCKET_TYPE -> RiskLevel.Low - ErrorType.ERROR_REDIRECT_LOOP -> RiskLevel.Low - ErrorType.ERROR_OFFLINE -> RiskLevel.Low - ErrorType.ERROR_NET_RESET -> RiskLevel.Low - ErrorType.ERROR_UNSAFE_CONTENT_TYPE -> RiskLevel.Low - ErrorType.ERROR_CORRUPTED_CONTENT -> RiskLevel.Low - ErrorType.ERROR_CONTENT_CRASHED -> RiskLevel.Low - ErrorType.ERROR_INVALID_CONTENT_ENCODING -> RiskLevel.Low - ErrorType.ERROR_UNKNOWN_HOST -> RiskLevel.Low - ErrorType.ERROR_MALFORMED_URI -> RiskLevel.Low - ErrorType.ERROR_FILE_NOT_FOUND -> RiskLevel.Low - ErrorType.ERROR_FILE_ACCESS_DENIED -> RiskLevel.Low - ErrorType.ERROR_PROXY_CONNECTION_REFUSED -> RiskLevel.Low - ErrorType.ERROR_UNKNOWN_PROXY_HOST -> RiskLevel.Low - ErrorType.ERROR_UNKNOWN_PROTOCOL -> RiskLevel.Low + ErrorType.ERROR_SECURITY_BAD_CERT, + ErrorType.ERROR_SECURITY_SSL, + ErrorType.ERROR_PORT_BLOCKED -> RiskLevel.Medium - // Medium risk errors - ErrorType.ERROR_SECURITY_BAD_CERT -> RiskLevel.Medium - ErrorType.ERROR_SECURITY_SSL -> RiskLevel.Medium - ErrorType.ERROR_PORT_BLOCKED -> RiskLevel.Medium - - // High risk errors - ErrorType.ERROR_SAFEBROWSING_HARMFUL_URI -> RiskLevel.High - ErrorType.ERROR_SAFEBROWSING_MALWARE_URI -> RiskLevel.High - ErrorType.ERROR_SAFEBROWSING_PHISHING_URI -> RiskLevel.High - ErrorType.ERROR_SAFEBROWSING_UNWANTED_URI -> RiskLevel.High - } + ErrorType.ERROR_SAFEBROWSING_HARMFUL_URI, + ErrorType.ERROR_SAFEBROWSING_MALWARE_URI, + ErrorType.ERROR_SAFEBROWSING_PHISHING_URI, + ErrorType.ERROR_SAFEBROWSING_UNWANTED_URI -> RiskLevel.High } - sealed class RiskLevel { - object Low : RiskLevel() - object Medium : RiskLevel() - object High : RiskLevel() + private enum class RiskLevel(@RawRes val htmlRes: Int, @RawRes val cssRes: Int) { + Low(R.raw.low_risk_error_pages, R.raw.low_and_medium_risk_error_style), + Medium(R.raw.medium_and_high_risk_error_pages, R.raw.low_and_medium_risk_error_style), + High(R.raw.medium_and_high_risk_error_pages, R.raw.high_risk_error_style), } } diff --git a/app/src/test/java/org/mozilla/fenix/AppRequestInterceptorTest.kt b/app/src/test/java/org/mozilla/fenix/AppRequestInterceptorTest.kt new file mode 100644 index 000000000..9351972a7 --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/AppRequestInterceptorTest.kt @@ -0,0 +1,112 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix + +import androidx.annotation.RawRes +import assertk.assertThat +import assertk.assertions.isEqualTo +import io.mockk.mockk +import kotlinx.coroutines.ObsoleteCoroutinesApi +import mozilla.components.browser.errorpages.ErrorPages +import mozilla.components.browser.errorpages.ErrorType +import mozilla.components.concept.engine.request.RequestInterceptor +import mozilla.components.support.test.robolectric.testContext +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config + +@UseExperimental(ObsoleteCoroutinesApi::class) +@RunWith(RobolectricTestRunner::class) +@Config(application = TestApplication::class) +class AppRequestInterceptorTest { + + private lateinit var interceptor: RequestInterceptor + + @Before + fun setUp() { + interceptor = AppRequestInterceptor(testContext) + } + + @Test + fun `onErrorRequest results in correct error page for low risk level error`() { + setOf( + ErrorType.UNKNOWN, + ErrorType.ERROR_NET_INTERRUPT, + ErrorType.ERROR_NET_TIMEOUT, + ErrorType.ERROR_CONNECTION_REFUSED, + ErrorType.ERROR_UNKNOWN_SOCKET_TYPE, + ErrorType.ERROR_REDIRECT_LOOP, + ErrorType.ERROR_OFFLINE, + ErrorType.ERROR_NET_RESET, + ErrorType.ERROR_UNSAFE_CONTENT_TYPE, + ErrorType.ERROR_CORRUPTED_CONTENT, + ErrorType.ERROR_CONTENT_CRASHED, + ErrorType.ERROR_INVALID_CONTENT_ENCODING, + ErrorType.ERROR_UNKNOWN_HOST, + ErrorType.ERROR_MALFORMED_URI, + ErrorType.ERROR_FILE_NOT_FOUND, + ErrorType.ERROR_FILE_ACCESS_DENIED, + ErrorType.ERROR_PROXY_CONNECTION_REFUSED, + ErrorType.ERROR_UNKNOWN_PROXY_HOST, + ErrorType.ERROR_UNKNOWN_PROTOCOL + ).forEach { error -> + val actualPage = createActualErrorPage(error) + val expectedPage = createExpectedErrorPage( + error = error, + html = R.raw.low_risk_error_pages, + css = R.raw.low_and_medium_risk_error_style + ) + + assertThat(actualPage).isEqualTo(expectedPage) + } + } + + @Test + fun `onErrorRequest results in correct error page for medium risk level error`() { + setOf( + ErrorType.ERROR_SECURITY_BAD_CERT, + ErrorType.ERROR_SECURITY_SSL, + ErrorType.ERROR_PORT_BLOCKED + ).forEach { error -> + val actualPage = createActualErrorPage(error) + val expectedPage = createExpectedErrorPage( + error = error, + html = R.raw.medium_and_high_risk_error_pages, + css = R.raw.low_and_medium_risk_error_style + ) + + assertThat(actualPage).isEqualTo(expectedPage) + } + } + + @Test + fun `onErrorRequest results in correct error page for high risk level error`() { + setOf( + ErrorType.ERROR_SAFEBROWSING_HARMFUL_URI, + ErrorType.ERROR_SAFEBROWSING_MALWARE_URI, + ErrorType.ERROR_SAFEBROWSING_PHISHING_URI, + ErrorType.ERROR_SAFEBROWSING_UNWANTED_URI + ).forEach { error -> + val actualPage = createActualErrorPage(error) + val expectedPage = createExpectedErrorPage( + error = error, + html = R.raw.medium_and_high_risk_error_pages, + css = R.raw.high_risk_error_style + ) + + assertThat(actualPage).isEqualTo(expectedPage) + } + } + + private fun createActualErrorPage(error: ErrorType): String { + return interceptor.onErrorRequest(session = mockk(), errorType = error, uri = null)?.data!! + } + + private fun createExpectedErrorPage(error: ErrorType, @RawRes html: Int, @RawRes css: Int): String { + return ErrorPages.createErrorPage(testContext, error, null, html, css) + } +}