Add tryGetHostFromUrl and update ExceptionDomains
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.ext.components
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import java.net.MalformedURLException
|
||||
import java.net.URL
|
||||
import org.mozilla.fenix.ext.tryGetHostFromUrl
|
||||
|
||||
class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
|
||||
override fun onLoadRequest(session: EngineSession, uri: String): RequestInterceptor.InterceptionResponse? {
|
||||
val host = try {
|
||||
URL(uri).host
|
||||
} catch (e: MalformedURLException) {
|
||||
uri
|
||||
}
|
||||
val host = uri.tryGetHostFromUrl()
|
||||
|
||||
adjustTrackingProtection(host, context, session)
|
||||
|
||||
|
@ -35,7 +30,7 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
|
|||
}
|
||||
|
||||
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
|
||||
if (trackingProtectionException || !trackingProtectionEnabled) {
|
||||
session.disableTrackingProtection()
|
||||
|
|
|
@ -6,73 +6,79 @@ package org.mozilla.fenix.exceptions
|
|||
|
||||
import android.content.Context
|
||||
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.
|
||||
*/
|
||||
object ExceptionDomains {
|
||||
private const val PREFERENCE_NAME = "exceptions"
|
||||
private const val KEY_DOMAINS = "exceptions_domains"
|
||||
private const val SEPARATOR = "@<;>@"
|
||||
class ExceptionDomains(context: Context) : PreferencesHolder {
|
||||
|
||||
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.
|
||||
*
|
||||
* @param context the application context
|
||||
* @return list of custom domains
|
||||
*/
|
||||
fun load(context: Context): List<String> {
|
||||
fun load(): List<String> {
|
||||
if (exceptions == null) {
|
||||
exceptions = (preferences(context)
|
||||
.getString(KEY_DOMAINS, "") ?: "")
|
||||
.split(SEPARATOR)
|
||||
.filter { !it.isEmpty() }
|
||||
exceptions = domains.split(SEPARATOR).filter { it.isNotEmpty() }
|
||||
}
|
||||
|
||||
return exceptions ?: listOf()
|
||||
return exceptions.orEmpty()
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the provided domains to preferences.
|
||||
*
|
||||
* @param context the application context
|
||||
* @param domains list of domains
|
||||
*/
|
||||
fun save(context: Context, domains: List<String>) {
|
||||
fun save(domains: List<String>) {
|
||||
exceptions = domains
|
||||
|
||||
preferences(context)
|
||||
.edit()
|
||||
.putString(KEY_DOMAINS, domains.joinToString(separator = SEPARATOR))
|
||||
.apply()
|
||||
this.domains = domains.joinToString(separator = SEPARATOR)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the provided domain to preferences.
|
||||
*
|
||||
* @param context the application context
|
||||
* @param domain the domain to add
|
||||
*/
|
||||
fun add(context: Context, domain: String) {
|
||||
val domains = mutableListOf<String>()
|
||||
domains.addAll(load(context))
|
||||
domains.add(domain)
|
||||
|
||||
save(context, domains)
|
||||
fun add(domain: String) {
|
||||
save(domains = load() + domain)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the provided domain from preferences.
|
||||
*
|
||||
* @param context the application context
|
||||
* @param domains the domain to remove
|
||||
*/
|
||||
fun remove(context: Context, domains: List<String>) {
|
||||
save(context, load(context) - domains)
|
||||
fun remove(domains: List<String>) {
|
||||
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() {
|
||||
viewLifecycleOwner.lifecycleScope.launch(IO) {
|
||||
val domains = ExceptionDomains.load(context!!)
|
||||
ExceptionDomains.remove(context!!, domains)
|
||||
ExceptionDomains(requireContext()).run {
|
||||
val domains = load()
|
||||
remove(domains)
|
||||
}
|
||||
reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteOneItem(item: ExceptionsItem) {
|
||||
viewLifecycleOwner.lifecycleScope.launch(IO) {
|
||||
ExceptionDomains.remove(context!!, listOf(item.url))
|
||||
ExceptionDomains(requireContext()).remove(listOf(item.url))
|
||||
reloadData()
|
||||
}
|
||||
}
|
||||
|
@ -89,12 +91,8 @@ class ExceptionsFragment : Fragment() {
|
|||
}
|
||||
|
||||
private fun loadAndMapExceptions(): List<ExceptionsItem> {
|
||||
return ExceptionDomains.load(context!!)
|
||||
.map { item ->
|
||||
ExceptionsItem(
|
||||
item
|
||||
)
|
||||
}
|
||||
return ExceptionDomains(requireContext()).load()
|
||||
.map { item -> ExceptionsItem(item) }
|
||||
}
|
||||
|
||||
private suspend fun reloadData() {
|
||||
|
|
|
@ -7,9 +7,9 @@ package org.mozilla.fenix.ext
|
|||
import android.content.Context
|
||||
import androidx.core.net.toUri
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import mozilla.components.support.ktx.android.net.hostWithoutCommonPrefixes
|
||||
import java.net.MalformedURLException
|
||||
import java.net.URL
|
||||
import mozilla.components.support.ktx.android.net.hostWithoutCommonPrefixes
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Returns **null** otherwise.
|
||||
* Tries to parse and get host part if this [String] is valid URL.
|
||||
* Otherwise returns the string.
|
||||
*/
|
||||
fun String?.getHostFromUrl(): String? = try {
|
||||
fun String.tryGetHostFromUrl(): String = try {
|
||||
URL(this).host
|
||||
} catch (e: MalformedURLException) {
|
||||
null
|
||||
this
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,7 +7,7 @@ package org.mozilla.fenix.library.history
|
|||
import androidx.paging.ItemKeyedDataSource
|
||||
import mozilla.components.concept.storage.VisitInfo
|
||||
import org.mozilla.fenix.components.history.PagedHistoryProvider
|
||||
import org.mozilla.fenix.ext.getHostFromUrl
|
||||
import org.mozilla.fenix.ext.tryGetHostFromUrl
|
||||
|
||||
class HistoryDataSource(
|
||||
private val historyProvider: PagedHistoryProvider
|
||||
|
@ -44,8 +44,7 @@ class HistoryDataSource(
|
|||
return { id, visit ->
|
||||
val title = visit.title
|
||||
?.takeIf(String::isNotEmpty)
|
||||
?: visit.url.getHostFromUrl()
|
||||
?: visit.url
|
||||
?: visit.url.tryGetHostFromUrl()
|
||||
|
||||
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.ext.components
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import org.mozilla.fenix.ext.tryGetHostFromUrl
|
||||
import org.mozilla.fenix.mvi.ActionBusFactory
|
||||
import org.mozilla.fenix.mvi.getAutoDisposeObservable
|
||||
import org.mozilla.fenix.mvi.getManagedEmitter
|
||||
import org.mozilla.fenix.settings.PhoneFeature
|
||||
import java.net.MalformedURLException
|
||||
import java.net.URL
|
||||
import com.google.android.material.R as MaterialR
|
||||
|
||||
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 }
|
||||
|
||||
private fun toggleTrackingProtection(context: Context, url: String) {
|
||||
val host = try {
|
||||
URL(url).host
|
||||
} catch (e: MalformedURLException) {
|
||||
url
|
||||
}
|
||||
val host = url.tryGetHostFromUrl()
|
||||
lifecycleScope.launch {
|
||||
if (!ExceptionDomains.load(context).contains(host)) {
|
||||
ExceptionDomains.add(context, host)
|
||||
} else {
|
||||
ExceptionDomains.remove(context, listOf(host))
|
||||
}
|
||||
ExceptionDomains(context).toggle(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.SOCIAL
|
||||
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.FINGERPRINTERS
|
||||
import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.SOCIAL_MEDIA_TRACKERS
|
||||
|
@ -57,21 +57,21 @@ class TrackerBuckets {
|
|||
when {
|
||||
CRYPTOMINING in item.trackingCategories -> {
|
||||
map[CRYPTOMINERS] = map[CRYPTOMINERS].orEmpty() +
|
||||
(item.url.getHostFromUrl() ?: item.url)
|
||||
item.url.tryGetHostFromUrl()
|
||||
}
|
||||
FINGERPRINTING in item.trackingCategories -> {
|
||||
map[FINGERPRINTERS] = map[FINGERPRINTERS].orEmpty() +
|
||||
(item.url.getHostFromUrl() ?: item.url)
|
||||
item.url.tryGetHostFromUrl()
|
||||
}
|
||||
SOCIAL in item.trackingCategories -> {
|
||||
map[SOCIAL_MEDIA_TRACKERS] = map[SOCIAL_MEDIA_TRACKERS].orEmpty() +
|
||||
(item.url.getHostFromUrl() ?: item.url)
|
||||
item.url.tryGetHostFromUrl()
|
||||
}
|
||||
AD in item.trackingCategories ||
|
||||
SOCIAL in item.trackingCategories ||
|
||||
ANALYTICS in item.trackingCategories -> {
|
||||
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.nav
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import java.net.MalformedURLException
|
||||
import java.net.URL
|
||||
import org.mozilla.fenix.ext.tryGetHostFromUrl
|
||||
|
||||
class TrackingProtectionPanelDialogFragment : AppCompatDialogFragment(), BackHandler {
|
||||
|
||||
|
@ -154,20 +153,12 @@ class TrackingProtectionPanelDialogFragment : AppCompatDialogFragment(), BackHan
|
|||
}
|
||||
|
||||
private fun toggleTrackingProtection(isEnabled: Boolean) {
|
||||
context?.let {
|
||||
val host = try {
|
||||
URL(url).host
|
||||
} catch (e: MalformedURLException) {
|
||||
url
|
||||
}
|
||||
context?.let { context ->
|
||||
val host = url.tryGetHostFromUrl()
|
||||
lifecycleScope.launch {
|
||||
if (!ExceptionDomains.load(it).contains(host)) {
|
||||
ExceptionDomains.add(it, host)
|
||||
} else {
|
||||
ExceptionDomains.remove(it, listOf(host))
|
||||
}
|
||||
ExceptionDomains(context).toggle(host)
|
||||
}
|
||||
it.components.useCases.sessionUseCases.reload.invoke()
|
||||
context.components.useCases.sessionUseCases.reload.invoke()
|
||||
}
|
||||
trackingProtectionStore.dispatch(TrackingProtectionAction.TrackerBlockingChanged(isEnabled))
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@ package org.mozilla.fenix.ext
|
|||
|
||||
import kotlinx.coroutines.ObsoleteCoroutinesApi
|
||||
import mozilla.components.support.test.robolectric.testContext
|
||||
import org.mozilla.fenix.TestApplication
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.mozilla.fenix.TestApplication
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
|
@ -16,31 +16,31 @@ import org.robolectric.annotation.Config
|
|||
class StringTest {
|
||||
|
||||
@Test
|
||||
fun `Replace`() {
|
||||
fun replace() {
|
||||
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)
|
||||
assertEquals(new, "moco and mofo are committed to the future of the internet")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Get Host From Url`() {
|
||||
fun `Try Get Host From Url`() {
|
||||
val urlTest = "http://www.example.com:1080/docs/resource1.html"
|
||||
var new = urlTest.getHostFromUrl()
|
||||
val new = urlTest.tryGetHostFromUrl()
|
||||
assertEquals(new, "www.example.com")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Url To Trimmed Host`() {
|
||||
val urlTest = "http://www.example.com:1080/docs/resource1.html"
|
||||
var new = urlTest.urlToTrimmedHost(testContext)
|
||||
val new = urlTest.urlToTrimmedHost(testContext)
|
||||
assertEquals(new, "example")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Simplified Url`() {
|
||||
val urlTest = "https://www.amazon.com"
|
||||
var new = urlTest.simplifiedUrl()
|
||||
val new = urlTest.simplifiedUrl()
|
||||
assertEquals(new, "amazon.com")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue