Add tryGetHostFromUrl and update ExceptionDomains

nightly-build-test
Tiger Oakes 5 years ago committed by Christian Sadilek
parent bea79436e8
commit 05a4faec78

@ -13,16 +13,11 @@ import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.exceptions.ExceptionDomains import org.mozilla.fenix.exceptions.ExceptionDomains
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.settings
import java.net.MalformedURLException import org.mozilla.fenix.ext.tryGetHostFromUrl
import java.net.URL
class AppRequestInterceptor(private val context: Context) : RequestInterceptor { class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
override fun onLoadRequest(session: EngineSession, uri: String): RequestInterceptor.InterceptionResponse? { override fun onLoadRequest(session: EngineSession, uri: String): RequestInterceptor.InterceptionResponse? {
val host = try { val host = uri.tryGetHostFromUrl()
URL(uri).host
} catch (e: MalformedURLException) {
uri
}
adjustTrackingProtection(host, context, session) adjustTrackingProtection(host, context, session)
@ -35,7 +30,7 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
} }
private fun adjustTrackingProtection(host: String, context: Context, session: EngineSession) { private fun adjustTrackingProtection(host: String, context: Context, session: EngineSession) {
val trackingProtectionException = ExceptionDomains.load(context).contains(host) val trackingProtectionException = ExceptionDomains(context).load().contains(host)
val trackingProtectionEnabled = context.settings.shouldUseTrackingProtection val trackingProtectionEnabled = context.settings.shouldUseTrackingProtection
if (trackingProtectionException || !trackingProtectionEnabled) { if (trackingProtectionException || !trackingProtectionEnabled) {
session.disableTrackingProtection() session.disableTrackingProtection()

@ -6,73 +6,79 @@ package org.mozilla.fenix.exceptions
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import mozilla.components.support.ktx.android.content.PreferencesHolder
import mozilla.components.support.ktx.android.content.stringPreference
/** /**
* Contains functionality to manage custom domains for allow-list. * Contains functionality to manage custom domains for allow-list.
*/ */
object ExceptionDomains { class ExceptionDomains(context: Context) : PreferencesHolder {
private const val PREFERENCE_NAME = "exceptions"
private const val KEY_DOMAINS = "exceptions_domains"
private const val SEPARATOR = "@<;>@"
private var exceptions: List<String>? = null override val preferences: SharedPreferences =
context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE)
private var domains by stringPreference(KEY_DOMAINS, default = "")
/** /**
* Loads the previously added/saved custom domains from preferences. * Loads the previously added/saved custom domains from preferences.
* *
* @param context the application context
* @return list of custom domains * @return list of custom domains
*/ */
fun load(context: Context): List<String> { fun load(): List<String> {
if (exceptions == null) { if (exceptions == null) {
exceptions = (preferences(context) exceptions = domains.split(SEPARATOR).filter { it.isNotEmpty() }
.getString(KEY_DOMAINS, "") ?: "")
.split(SEPARATOR)
.filter { !it.isEmpty() }
} }
return exceptions ?: listOf() return exceptions.orEmpty()
} }
/** /**
* Saves the provided domains to preferences. * Saves the provided domains to preferences.
* *
* @param context the application context
* @param domains list of domains * @param domains list of domains
*/ */
fun save(context: Context, domains: List<String>) { fun save(domains: List<String>) {
exceptions = domains exceptions = domains
preferences(context) this.domains = domains.joinToString(separator = SEPARATOR)
.edit()
.putString(KEY_DOMAINS, domains.joinToString(separator = SEPARATOR))
.apply()
} }
/** /**
* Adds the provided domain to preferences. * Adds the provided domain to preferences.
* *
* @param context the application context
* @param domain the domain to add * @param domain the domain to add
*/ */
fun add(context: Context, domain: String) { fun add(domain: String) {
val domains = mutableListOf<String>() save(domains = load() + domain)
domains.addAll(load(context))
domains.add(domain)
save(context, domains)
} }
/** /**
* Removes the provided domain from preferences. * Removes the provided domain from preferences.
* *
* @param context the application context
* @param domains the domain to remove * @param domains the domain to remove
*/ */
fun remove(context: Context, domains: List<String>) { fun remove(domains: List<String>) {
save(context, load(context) - domains) save(domains = load() - domains)
} }
private fun preferences(context: Context): SharedPreferences = /**
context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE) * Adds or removes the provided domain from preferences.
*
* If present, the domain will be removed. Otherwise, it will be added.
*/
fun toggle(domain: String) {
if (domain in load()) {
remove(listOf(domain))
} else {
add(domain)
}
}
companion object {
private const val PREFERENCE_NAME = "exceptions"
private const val KEY_DOMAINS = "exceptions_domains"
private const val SEPARATOR = "@<;>@"
private var exceptions: List<String>? = null
}
} }

@ -66,15 +66,17 @@ class ExceptionsFragment : Fragment() {
private fun deleteAllItems() { private fun deleteAllItems() {
viewLifecycleOwner.lifecycleScope.launch(IO) { viewLifecycleOwner.lifecycleScope.launch(IO) {
val domains = ExceptionDomains.load(context!!) ExceptionDomains(requireContext()).run {
ExceptionDomains.remove(context!!, domains) val domains = load()
remove(domains)
}
reloadData() reloadData()
} }
} }
private fun deleteOneItem(item: ExceptionsItem) { private fun deleteOneItem(item: ExceptionsItem) {
viewLifecycleOwner.lifecycleScope.launch(IO) { viewLifecycleOwner.lifecycleScope.launch(IO) {
ExceptionDomains.remove(context!!, listOf(item.url)) ExceptionDomains(requireContext()).remove(listOf(item.url))
reloadData() reloadData()
} }
} }
@ -89,12 +91,8 @@ class ExceptionsFragment : Fragment() {
} }
private fun loadAndMapExceptions(): List<ExceptionsItem> { private fun loadAndMapExceptions(): List<ExceptionsItem> {
return ExceptionDomains.load(context!!) return ExceptionDomains(requireContext()).load()
.map { item -> .map { item -> ExceptionsItem(item) }
ExceptionsItem(
item
)
}
} }
private suspend fun reloadData() { private suspend fun reloadData() {

@ -7,9 +7,9 @@ package org.mozilla.fenix.ext
import android.content.Context import android.content.Context
import androidx.core.net.toUri import androidx.core.net.toUri
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import mozilla.components.support.ktx.android.net.hostWithoutCommonPrefixes
import java.net.MalformedURLException import java.net.MalformedURLException
import java.net.URL import java.net.URL
import mozilla.components.support.ktx.android.net.hostWithoutCommonPrefixes
/** /**
* Replaces the keys with the values with the map provided. * Replaces the keys with the values with the map provided.
@ -21,13 +21,13 @@ fun String.replace(pairs: Map<String, String>): String {
} }
/** /**
* Try to parse and get host part if this [String] is valid URL. * Tries to parse and get host part if this [String] is valid URL.
* Returns **null** otherwise. * Otherwise returns the string.
*/ */
fun String?.getHostFromUrl(): String? = try { fun String.tryGetHostFromUrl(): String = try {
URL(this).host URL(this).host
} catch (e: MalformedURLException) { } catch (e: MalformedURLException) {
null this
} }
/** /**

@ -7,7 +7,7 @@ package org.mozilla.fenix.library.history
import androidx.paging.ItemKeyedDataSource import androidx.paging.ItemKeyedDataSource
import mozilla.components.concept.storage.VisitInfo import mozilla.components.concept.storage.VisitInfo
import org.mozilla.fenix.components.history.PagedHistoryProvider import org.mozilla.fenix.components.history.PagedHistoryProvider
import org.mozilla.fenix.ext.getHostFromUrl import org.mozilla.fenix.ext.tryGetHostFromUrl
class HistoryDataSource( class HistoryDataSource(
private val historyProvider: PagedHistoryProvider private val historyProvider: PagedHistoryProvider
@ -44,8 +44,7 @@ class HistoryDataSource(
return { id, visit -> return { id, visit ->
val title = visit.title val title = visit.title
?.takeIf(String::isNotEmpty) ?.takeIf(String::isNotEmpty)
?: visit.url.getHostFromUrl() ?: visit.url.tryGetHostFromUrl()
?: visit.url
HistoryItem(offset + id, title, visit.url, visit.visitTime) HistoryItem(offset + id, title, visit.url, visit.visitTime)
} }

@ -39,12 +39,11 @@ import org.mozilla.fenix.browser.BrowserFragment
import org.mozilla.fenix.exceptions.ExceptionDomains import org.mozilla.fenix.exceptions.ExceptionDomains
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.tryGetHostFromUrl
import org.mozilla.fenix.mvi.ActionBusFactory import org.mozilla.fenix.mvi.ActionBusFactory
import org.mozilla.fenix.mvi.getAutoDisposeObservable import org.mozilla.fenix.mvi.getAutoDisposeObservable
import org.mozilla.fenix.mvi.getManagedEmitter import org.mozilla.fenix.mvi.getManagedEmitter
import org.mozilla.fenix.settings.PhoneFeature import org.mozilla.fenix.settings.PhoneFeature
import java.net.MalformedURLException
import java.net.URL
import com.google.android.material.R as MaterialR import com.google.android.material.R as MaterialR
private const val REQUEST_CODE_QUICK_SETTINGS_PERMISSIONS = 4 private const val REQUEST_CODE_QUICK_SETTINGS_PERMISSIONS = 4
@ -155,17 +154,9 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() {
requestCode == REQUEST_CODE_QUICK_SETTINGS_PERMISSIONS && grantResults.all { it == PERMISSION_GRANTED } requestCode == REQUEST_CODE_QUICK_SETTINGS_PERMISSIONS && grantResults.all { it == PERMISSION_GRANTED }
private fun toggleTrackingProtection(context: Context, url: String) { private fun toggleTrackingProtection(context: Context, url: String) {
val host = try { val host = url.tryGetHostFromUrl()
URL(url).host
} catch (e: MalformedURLException) {
url
}
lifecycleScope.launch { lifecycleScope.launch {
if (!ExceptionDomains.load(context).contains(host)) { ExceptionDomains(context).toggle(host)
ExceptionDomains.add(context, host)
} else {
ExceptionDomains.remove(context, listOf(host))
}
} }
} }

@ -10,7 +10,7 @@ import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.
import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.TrackingCategory.FINGERPRINTING import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.TrackingCategory.FINGERPRINTING
import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.TrackingCategory.SOCIAL import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.TrackingCategory.SOCIAL
import mozilla.components.concept.engine.content.blocking.Tracker import mozilla.components.concept.engine.content.blocking.Tracker
import org.mozilla.fenix.ext.getHostFromUrl import org.mozilla.fenix.ext.tryGetHostFromUrl
import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.CRYPTOMINERS import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.CRYPTOMINERS
import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.FINGERPRINTERS import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.FINGERPRINTERS
import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.SOCIAL_MEDIA_TRACKERS import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.SOCIAL_MEDIA_TRACKERS
@ -57,21 +57,21 @@ class TrackerBuckets {
when { when {
CRYPTOMINING in item.trackingCategories -> { CRYPTOMINING in item.trackingCategories -> {
map[CRYPTOMINERS] = map[CRYPTOMINERS].orEmpty() + map[CRYPTOMINERS] = map[CRYPTOMINERS].orEmpty() +
(item.url.getHostFromUrl() ?: item.url) item.url.tryGetHostFromUrl()
} }
FINGERPRINTING in item.trackingCategories -> { FINGERPRINTING in item.trackingCategories -> {
map[FINGERPRINTERS] = map[FINGERPRINTERS].orEmpty() + map[FINGERPRINTERS] = map[FINGERPRINTERS].orEmpty() +
(item.url.getHostFromUrl() ?: item.url) item.url.tryGetHostFromUrl()
} }
SOCIAL in item.trackingCategories -> { SOCIAL in item.trackingCategories -> {
map[SOCIAL_MEDIA_TRACKERS] = map[SOCIAL_MEDIA_TRACKERS].orEmpty() + map[SOCIAL_MEDIA_TRACKERS] = map[SOCIAL_MEDIA_TRACKERS].orEmpty() +
(item.url.getHostFromUrl() ?: item.url) item.url.tryGetHostFromUrl()
} }
AD in item.trackingCategories || AD in item.trackingCategories ||
SOCIAL in item.trackingCategories || SOCIAL in item.trackingCategories ||
ANALYTICS in item.trackingCategories -> { ANALYTICS in item.trackingCategories -> {
map[TRACKING_CONTENT] = map[TRACKING_CONTENT].orEmpty() + map[TRACKING_CONTENT] = map[TRACKING_CONTENT].orEmpty() +
(item.url.getHostFromUrl() ?: item.url) item.url.tryGetHostFromUrl()
} }
} }
} }

@ -33,8 +33,7 @@ import org.mozilla.fenix.exceptions.ExceptionDomains
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.nav import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.requireComponents
import java.net.MalformedURLException import org.mozilla.fenix.ext.tryGetHostFromUrl
import java.net.URL
class TrackingProtectionPanelDialogFragment : AppCompatDialogFragment(), BackHandler { class TrackingProtectionPanelDialogFragment : AppCompatDialogFragment(), BackHandler {
@ -154,20 +153,12 @@ class TrackingProtectionPanelDialogFragment : AppCompatDialogFragment(), BackHan
} }
private fun toggleTrackingProtection(isEnabled: Boolean) { private fun toggleTrackingProtection(isEnabled: Boolean) {
context?.let { context?.let { context ->
val host = try { val host = url.tryGetHostFromUrl()
URL(url).host
} catch (e: MalformedURLException) {
url
}
lifecycleScope.launch { lifecycleScope.launch {
if (!ExceptionDomains.load(it).contains(host)) { ExceptionDomains(context).toggle(host)
ExceptionDomains.add(it, host)
} else {
ExceptionDomains.remove(it, listOf(host))
}
} }
it.components.useCases.sessionUseCases.reload.invoke() context.components.useCases.sessionUseCases.reload.invoke()
} }
trackingProtectionStore.dispatch(TrackingProtectionAction.TrackerBlockingChanged(isEnabled)) trackingProtectionStore.dispatch(TrackingProtectionAction.TrackerBlockingChanged(isEnabled))
} }

@ -2,10 +2,10 @@ package org.mozilla.fenix.ext
import kotlinx.coroutines.ObsoleteCoroutinesApi import kotlinx.coroutines.ObsoleteCoroutinesApi
import mozilla.components.support.test.robolectric.testContext import mozilla.components.support.test.robolectric.testContext
import org.mozilla.fenix.TestApplication import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.junit.Assert.assertEquals import org.mozilla.fenix.TestApplication
import org.robolectric.RobolectricTestRunner import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config import org.robolectric.annotation.Config
@ -16,31 +16,31 @@ import org.robolectric.annotation.Config
class StringTest { class StringTest {
@Test @Test
fun `Replace`() { fun replace() {
val chars = mapOf("Mozilla Corporation" to "moco", "Mozilla Foundation" to "mofo") val chars = mapOf("Mozilla Corporation" to "moco", "Mozilla Foundation" to "mofo")
var sentence = "Mozilla Corporation and Mozilla Foundation are committed to the future of the internet" val sentence = "Mozilla Corporation and Mozilla Foundation are committed to the future of the internet"
val new = sentence.replace(chars) val new = sentence.replace(chars)
assertEquals(new, "moco and mofo are committed to the future of the internet") assertEquals(new, "moco and mofo are committed to the future of the internet")
} }
@Test @Test
fun `Get Host From Url`() { fun `Try Get Host From Url`() {
val urlTest = "http://www.example.com:1080/docs/resource1.html" val urlTest = "http://www.example.com:1080/docs/resource1.html"
var new = urlTest.getHostFromUrl() val new = urlTest.tryGetHostFromUrl()
assertEquals(new, "www.example.com") assertEquals(new, "www.example.com")
} }
@Test @Test
fun `Url To Trimmed Host`() { fun `Url To Trimmed Host`() {
val urlTest = "http://www.example.com:1080/docs/resource1.html" val urlTest = "http://www.example.com:1080/docs/resource1.html"
var new = urlTest.urlToTrimmedHost(testContext) val new = urlTest.urlToTrimmedHost(testContext)
assertEquals(new, "example") assertEquals(new, "example")
} }
@Test @Test
fun `Simplified Url`() { fun `Simplified Url`() {
val urlTest = "https://www.amazon.com" val urlTest = "https://www.amazon.com"
var new = urlTest.simplifiedUrl() val new = urlTest.simplifiedUrl()
assertEquals(new, "amazon.com") assertEquals(new, "amazon.com")
} }
} }

Loading…
Cancel
Save