1
0
Fork 0
fenix/app/src/main/java/org/mozilla/fenix/AppRequestInterceptor.kt

119 lines
5.1 KiB
Kotlin

/* 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 android.content.Context
import mozilla.components.browser.errorpages.ErrorPages
import mozilla.components.browser.errorpages.ErrorType
import mozilla.components.concept.engine.EngineSession
import mozilla.components.concept.engine.request.RequestInterceptor
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.exceptions.ExceptionDomains
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.ext.tryGetHostFromUrl
class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
override fun onLoadRequest(session: EngineSession, uri: String): RequestInterceptor.InterceptionResponse? {
val host = uri.tryGetHostFromUrl()
adjustTrackingProtection(host, context, session)
// WebChannel-driven authentication does not require a separate redirect interceptor.
return if (context.isInExperiment(Experiments.asFeatureWebChannelsDisabled)) {
context.components.services.accountsAuthFeature.interceptor.onLoadRequest(session, uri)
} else {
null
}
}
private fun adjustTrackingProtection(host: String, context: Context, session: EngineSession) {
val trackingProtectionException = ExceptionDomains(context).load().contains(host)
val trackingProtectionEnabled = context.settings().shouldUseTrackingProtection
if (trackingProtectionException || !trackingProtectionEnabled) {
session.disableTrackingProtection()
} else {
val core = context.components.core
val policy = core.createTrackingProtectionPolicy(normalMode = true)
core.engine.settings.trackingProtectionPolicy = policy
session.enableTrackingProtection(policy)
}
}
override fun onErrorRequest(
session: EngineSession,
errorType: ErrorType,
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)
)
}
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 {
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
// 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
}
}
sealed class RiskLevel {
object Low : RiskLevel()
object Medium : RiskLevel()
object High : RiskLevel()
}
}