1
0
Fork 0

Add tryGetHostFromUrl and update ExceptionDomains

master
Tiger Oakes 2019-09-13 14:43:54 -07:00 committed by Christian Sadilek
parent bea79436e8
commit 05a4faec78
9 changed files with 74 additions and 94 deletions

View File

@ -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()

View File

@ -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
}
}

View File

@ -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() {

View File

@ -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
}
/**

View File

@ -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)
}

View File

@ -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)
}
}

View File

@ -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()
}
}
}

View File

@ -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))
}

View File

@ -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")
}
}