summaryrefslogtreecommitdiff
path: root/trackers
diff options
context:
space:
mode:
Diffstat (limited to 'trackers')
-rw-r--r--trackers/build.gradle9
-rw-r--r--trackers/src/main/AndroidManifest.xml5
-rw-r--r--trackers/src/main/java/foundation/e/advancedprivacy/trackers/KoinModule.kt72
-rw-r--r--trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/ETrackersResponse.kt10
-rw-r--r--trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/RemoteTrackersListRepository.kt61
-rw-r--r--trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/StatsDatabase.kt (renamed from trackers/src/main/java/foundation/e/privacymodules/trackers/data/StatsDatabase.kt)22
-rw-r--r--trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/TrackersRepository.kt109
-rw-r--r--trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/WhitelistRepository.kt (renamed from trackers/src/main/java/foundation/e/privacymodules/trackers/data/WhitelistRepository.kt)46
-rw-r--r--trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/entities/Tracker.kt (renamed from trackers/src/main/java/foundation/e/privacymodules/trackers/api/Tracker.kt)2
-rw-r--r--trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/DNSBlocker.kt (renamed from trackers/src/main/java/foundation/e/privacymodules/trackers/DNSBlockerRunnable.kt)68
-rw-r--r--trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/StatisticsUseCase.kt (renamed from trackers/src/main/java/foundation/e/privacymodules/trackers/data/StatsRepository.kt)57
-rw-r--r--trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/TrackersLogger.kt (renamed from trackers/src/main/java/foundation/e/privacymodules/trackers/TrackersLogger.kt)49
-rw-r--r--trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/UpdateTrackerListUseCase.kt29
-rw-r--r--trackers/src/main/java/foundation/e/advancedprivacy/trackers/services/DNSBlockerService.kt (renamed from trackers/src/main/java/foundation/e/privacymodules/trackers/DNSBlockerService.kt)45
-rw-r--r--trackers/src/main/java/foundation/e/advancedprivacy/trackers/services/ForegroundStarter.kt (renamed from trackers/src/main/java/foundation/e/privacymodules/trackers/ForegroundStarter.kt)2
-rw-r--r--trackers/src/main/java/foundation/e/advancedprivacy/trackers/services/UpdateTrackersWorker.kt60
-rw-r--r--trackers/src/main/java/foundation/e/privacymodules/trackers/api/BlockTrackersPrivacyModule.kt98
-rw-r--r--trackers/src/main/java/foundation/e/privacymodules/trackers/api/IBlockTrackersPrivacyModule.kt98
-rw-r--r--trackers/src/main/java/foundation/e/privacymodules/trackers/api/ITrackTrackersPrivacyModule.kt110
-rw-r--r--trackers/src/main/java/foundation/e/privacymodules/trackers/api/TrackTrackersPrivacyModule.kt126
-rw-r--r--trackers/src/main/java/foundation/e/privacymodules/trackers/data/TrackersRepository.kt57
21 files changed, 474 insertions, 661 deletions
diff --git a/trackers/build.gradle b/trackers/build.gradle
index bb9489a..737db5a 100644
--- a/trackers/build.gradle
+++ b/trackers/build.gradle
@@ -1,4 +1,5 @@
/*
+ Copyright (C) 2023 MURENA SAS
Copyright (C) 2022 ECORP
This program is free software; you can redistribute it and/or
@@ -42,9 +43,15 @@ android {
}
dependencies {
- implementation project(':privacymodule-api')
+ implementation project(':core')
implementation(
+ libs.androidx.work.ktx,
+ libs.bundles.koin,
libs.bundles.kotlin.android.coroutines,
+ libs.google.gson,
+ libs.retrofit,
+ libs.retrofit.scalars,
+
libs.timber
)
}
diff --git a/trackers/src/main/AndroidManifest.xml b/trackers/src/main/AndroidManifest.xml
index debdf61..615d310 100644
--- a/trackers/src/main/AndroidManifest.xml
+++ b/trackers/src/main/AndroidManifest.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
+ Copyright (C) 2023 MURENA SAS
Copyright (C) 2022 ECORP
This program is free software: you can redistribute it and/or modify
@@ -16,7 +17,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="foundation.e.privacymodules.trackers">
+ package="foundation.e.advancedprivacy.trackers">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
@@ -29,7 +30,7 @@
<application>
<service
- android:name="foundation.e.privacymodules.trackers.DNSBlockerService"
+ android:name="foundation.e.advancedprivacy.trackers.services.DNSBlockerService"
android:enabled="true"
android:exported="true" />
</application>
diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/KoinModule.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/KoinModule.kt
new file mode 100644
index 0000000..0cfb69c
--- /dev/null
+++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/KoinModule.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 MURENA SAS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package foundation.e.advancedprivacy.trackers
+
+import foundation.e.advancedprivacy.data.repositories.RemoteTrackersListRepository
+import foundation.e.advancedprivacy.trackers.data.StatsDatabase
+import foundation.e.advancedprivacy.trackers.data.TrackersRepository
+import foundation.e.advancedprivacy.trackers.data.WhitelistRepository
+import foundation.e.advancedprivacy.trackers.domain.usecases.DNSBlocker
+import foundation.e.advancedprivacy.trackers.domain.usecases.StatisticsUseCase
+import foundation.e.advancedprivacy.trackers.domain.usecases.TrackersLogger
+import foundation.e.advancedprivacy.trackers.domain.usecases.UpdateTrackerListUseCase
+import org.koin.android.ext.koin.androidContext
+import org.koin.core.module.dsl.factoryOf
+import org.koin.core.module.dsl.singleOf
+import org.koin.dsl.module
+
+val trackersModule = module {
+
+ factoryOf(::RemoteTrackersListRepository)
+ factoryOf(::UpdateTrackerListUseCase)
+
+ singleOf(::TrackersRepository)
+ single {
+ StatsDatabase(
+ context = androidContext(),
+ trackersRepository = get()
+ )
+ }
+
+ single {
+ StatisticsUseCase(
+ database = get(),
+ appListsRepository = get()
+ )
+ }
+
+ single {
+ WhitelistRepository(
+ context = androidContext(),
+ appListsRepository = get()
+ )
+ }
+
+ factory {
+ DNSBlocker(
+ context = androidContext(),
+ trackersLogger = get(),
+ trackersRepository = get(),
+ whitelistRepository = get()
+ )
+ }
+
+ factory {
+ TrackersLogger(statisticsUseCase = get())
+ }
+}
diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/ETrackersResponse.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/ETrackersResponse.kt
new file mode 100644
index 0000000..1b38ecf
--- /dev/null
+++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/ETrackersResponse.kt
@@ -0,0 +1,10 @@
+package foundation.e.advancedprivacy.trackers.data
+
+data class ETrackersResponse(val trackers: List<ETracker>) {
+ data class ETracker(
+ val id: String?,
+ val hostnames: List<String>?,
+ val name: String?,
+ val exodusId: String?
+ )
+}
diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/RemoteTrackersListRepository.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/RemoteTrackersListRepository.kt
new file mode 100644
index 0000000..c2c0768
--- /dev/null
+++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/RemoteTrackersListRepository.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2022 E FOUNDATION
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package foundation.e.advancedprivacy.data.repositories
+
+import retrofit2.Retrofit
+import retrofit2.converter.scalars.ScalarsConverterFactory
+import retrofit2.http.GET
+import timber.log.Timber
+import java.io.File
+import java.io.FileWriter
+import java.io.IOException
+import java.io.PrintWriter
+
+class RemoteTrackersListRepository {
+
+ fun saveData(file: File, data: String): Boolean {
+ try {
+ val fos = FileWriter(file, false)
+ val ps = PrintWriter(fos)
+ ps.apply {
+ print(data)
+ flush()
+ close()
+ }
+ return true
+ } catch (e: IOException) {
+ Timber.e("While saving tracker file.", e)
+ }
+ return false
+ }
+}
+
+interface ETrackersApi {
+ companion object {
+ fun build(): ETrackersApi {
+ val retrofit = Retrofit.Builder()
+ .baseUrl("https://gitlab.e.foundation/e/os/tracker-list/-/raw/main/")
+ .addConverterFactory(ScalarsConverterFactory.create())
+ .build()
+ return retrofit.create(ETrackersApi::class.java)
+ }
+ }
+
+ @GET("list/e_trackers.json")
+ suspend fun trackers(): String
+}
diff --git a/trackers/src/main/java/foundation/e/privacymodules/trackers/data/StatsDatabase.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/StatsDatabase.kt
index 4d287d4..6aa76cf 100644
--- a/trackers/src/main/java/foundation/e/privacymodules/trackers/data/StatsDatabase.kt
+++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/StatsDatabase.kt
@@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package foundation.e.privacymodules.trackers.data
+package foundation.e.advancedprivacy.trackers.data
import android.content.ContentValues
import android.content.Context
@@ -25,13 +25,13 @@ import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.provider.BaseColumns
import androidx.core.database.getStringOrNull
-import foundation.e.privacymodules.trackers.api.Tracker
-import foundation.e.privacymodules.trackers.data.StatsDatabase.AppTrackerEntry.COLUMN_NAME_APPID
-import foundation.e.privacymodules.trackers.data.StatsDatabase.AppTrackerEntry.COLUMN_NAME_NUMBER_BLOCKED
-import foundation.e.privacymodules.trackers.data.StatsDatabase.AppTrackerEntry.COLUMN_NAME_NUMBER_CONTACTED
-import foundation.e.privacymodules.trackers.data.StatsDatabase.AppTrackerEntry.COLUMN_NAME_TIMESTAMP
-import foundation.e.privacymodules.trackers.data.StatsDatabase.AppTrackerEntry.COLUMN_NAME_TRACKER
-import foundation.e.privacymodules.trackers.data.StatsDatabase.AppTrackerEntry.TABLE_NAME
+import foundation.e.advancedprivacy.trackers.data.StatsDatabase.AppTrackerEntry.COLUMN_NAME_APPID
+import foundation.e.advancedprivacy.trackers.data.StatsDatabase.AppTrackerEntry.COLUMN_NAME_NUMBER_BLOCKED
+import foundation.e.advancedprivacy.trackers.data.StatsDatabase.AppTrackerEntry.COLUMN_NAME_NUMBER_CONTACTED
+import foundation.e.advancedprivacy.trackers.data.StatsDatabase.AppTrackerEntry.COLUMN_NAME_TIMESTAMP
+import foundation.e.advancedprivacy.trackers.data.StatsDatabase.AppTrackerEntry.COLUMN_NAME_TRACKER
+import foundation.e.advancedprivacy.trackers.data.StatsDatabase.AppTrackerEntry.TABLE_NAME
+import foundation.e.advancedprivacy.trackers.domain.entities.Tracker
import timber.log.Timber
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
@@ -39,7 +39,10 @@ import java.time.temporal.ChronoUnit
import java.time.temporal.TemporalUnit
import java.util.concurrent.TimeUnit
-class StatsDatabase(context: Context) :
+class StatsDatabase(
+ context: Context,
+ private val trackersRepository: TrackersRepository
+) :
SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {
companion object {
@@ -84,7 +87,6 @@ class StatsDatabase(context: Context) :
)
private val lock = Any()
- private val trackersRepository = TrackersRepository.getInstance()
override fun onCreate(db: SQLiteDatabase) {
db.execSQL(SQL_CREATE_TABLE)
diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/TrackersRepository.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/TrackersRepository.kt
new file mode 100644
index 0000000..a7d5e49
--- /dev/null
+++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/TrackersRepository.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2022 E FOUNDATION
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package foundation.e.advancedprivacy.trackers.data
+
+import android.content.Context
+import com.google.gson.Gson
+import foundation.e.advancedprivacy.trackers.domain.entities.Tracker
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import timber.log.Timber
+import java.io.File
+import java.io.FileInputStream
+import java.io.InputStreamReader
+
+class TrackersRepository(
+ private val context: Context,
+ coroutineScope: CoroutineScope
+) {
+
+ private var trackersById: Map<String, Tracker> = HashMap()
+ private var hostnameToId: Map<String, String> = HashMap()
+
+ private val eTrackerFileName = "e_trackers.json"
+ val eTrackerFile = File(context.filesDir.absolutePath, eTrackerFileName)
+
+ init {
+ coroutineScope.launch(Dispatchers.IO) {
+ initTrackersFile()
+ }
+ }
+ fun initTrackersFile() {
+ try {
+ var inputStream = context.assets.open(eTrackerFileName)
+ if (eTrackerFile.exists()) {
+ inputStream = FileInputStream(eTrackerFile)
+ }
+ val reader = InputStreamReader(inputStream, "UTF-8")
+ val trackerResponse =
+ Gson().fromJson(reader, ETrackersResponse::class.java)
+
+ setTrackersList(mapper(trackerResponse))
+
+ reader.close()
+ inputStream.close()
+ } catch (e: Exception) {
+ Timber.e("While parsing trackers in assets", e)
+ }
+ }
+
+ private fun mapper(response: ETrackersResponse): List<Tracker> {
+ return response.trackers.mapNotNull {
+ try {
+ it.toTracker()
+ } catch (e: Exception) {
+ null
+ }
+ }
+ }
+
+ private fun ETrackersResponse.ETracker.toTracker(): Tracker {
+ return Tracker(
+ id = id!!,
+ hostnames = hostnames!!.toSet(),
+ label = name!!,
+ exodusId = exodusId
+ )
+ }
+
+ private fun setTrackersList(list: List<Tracker>) {
+ val trackersById: MutableMap<String, Tracker> = HashMap()
+ val hostnameToId: MutableMap<String, String> = HashMap()
+ list.forEach { tracker ->
+ trackersById[tracker.id] = tracker
+ for (hostname in tracker.hostnames) {
+ hostnameToId[hostname] = tracker.id
+ }
+ }
+ this.trackersById = trackersById
+ this.hostnameToId = hostnameToId
+ }
+
+ fun isTracker(hostname: String?): Boolean {
+ return hostnameToId.containsKey(hostname)
+ }
+
+ fun getTrackerId(hostname: String?): String? {
+ return hostnameToId[hostname]
+ }
+
+ fun getTracker(id: String?): Tracker? {
+ return trackersById[id]
+ }
+}
diff --git a/trackers/src/main/java/foundation/e/privacymodules/trackers/data/WhitelistRepository.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/WhitelistRepository.kt
index 2763d06..429c5e9 100644
--- a/trackers/src/main/java/foundation/e/privacymodules/trackers/data/WhitelistRepository.kt
+++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/data/WhitelistRepository.kt
@@ -16,15 +16,19 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package foundation.e.privacymodules.trackers.data
+package foundation.e.advancedprivacy.trackers.data
import android.content.Context
import android.content.SharedPreferences
-import foundation.e.privacymodules.permissions.data.ApplicationDescription
-import foundation.e.privacymodules.trackers.api.Tracker
+import foundation.e.advancedprivacy.data.repositories.AppListsRepository
+import foundation.e.advancedprivacy.domain.entities.ApplicationDescription
+import foundation.e.advancedprivacy.trackers.domain.entities.Tracker
import java.io.File
-class WhitelistRepository private constructor(context: Context) {
+class WhitelistRepository(
+ context: Context,
+ private val appListsRepository: AppListsRepository
+) {
private var appsWhitelist: Set<String> = HashSet()
private var appUidsWhitelist: Set<Int> = HashSet()
@@ -32,7 +36,6 @@ class WhitelistRepository private constructor(context: Context) {
private var trackersWhitelistByUid: Map<Int, MutableSet<String>> = HashMap()
private val prefs: SharedPreferences
- private var getAppByAPId: ((String) -> ApplicationDescription?)? = null
companion object {
private const val SHARED_PREFS_FILE = "trackers_whitelist_v2"
@@ -41,30 +44,17 @@ class WhitelistRepository private constructor(context: Context) {
private const val KEY_APP_TRACKERS_WHITELIST_PREFIX = "app_trackers_whitelist_"
private const val SHARED_PREFS_FILE_V1 = "trackers_whitelist.prefs"
-
- private var instance: WhitelistRepository? = null
- fun getInstance(context: Context): WhitelistRepository {
- return instance ?: WhitelistRepository(context).apply { instance = this }
- }
}
init {
prefs = context.getSharedPreferences(SHARED_PREFS_FILE, Context.MODE_PRIVATE)
reloadCache()
+ migrate(context)
}
- fun setAppGetters(
- context: Context,
- getAppByAPId: (String) -> ApplicationDescription?,
- getAppByUid: (Int) -> ApplicationDescription?
- ) {
- this.getAppByAPId = getAppByAPId
- migrate(context, getAppByUid)
- }
-
- private fun migrate(context: Context, getAppByUid: (Int) -> ApplicationDescription?) {
+ private fun migrate(context: Context) {
if (context.sharedPreferencesExists(SHARED_PREFS_FILE_V1)) {
- migrate1To2(context, getAppByUid)
+ migrate1To2(context)
}
}
@@ -74,7 +64,7 @@ class WhitelistRepository private constructor(context: Context) {
).exists()
}
- private fun migrate1To2(context: Context, getAppByUid: (Int) -> ApplicationDescription?) {
+ private fun migrate1To2(context: Context) {
val prefsV1 = context.getSharedPreferences(SHARED_PREFS_FILE_V1, Context.MODE_PRIVATE)
val editorV2 = prefs.edit()
@@ -83,7 +73,7 @@ class WhitelistRepository private constructor(context: Context) {
val apIds = prefsV1.getStringSet(KEY_APPS_WHITELIST, HashSet())?.mapNotNull {
try {
val uid = it.toInt()
- getAppByUid(uid)?.apId
+ appListsRepository.getApp(uid)?.apId
} catch (e: Exception) { null }
}?.toSet() ?: HashSet()
@@ -93,7 +83,7 @@ class WhitelistRepository private constructor(context: Context) {
if (key.startsWith(KEY_APP_TRACKERS_WHITELIST_PREFIX)) {
try {
val uid = key.substring(KEY_APP_TRACKERS_WHITELIST_PREFIX.length).toInt()
- val apId = getAppByUid(uid)?.apId
+ val apId = appListsRepository.getApp(uid)?.apId
apId?.let {
val trackers = prefsV1.getStringSet(key, emptySet())
editorV2.putStringSet(buildAppTrackersKey(apId), trackers)
@@ -117,13 +107,13 @@ class WhitelistRepository private constructor(context: Context) {
private fun reloadAppsWhiteList() {
appsWhitelist = prefs.getStringSet(KEY_APPS_WHITELIST, HashSet()) ?: HashSet()
appUidsWhitelist = appsWhitelist
- .mapNotNull { apId -> getAppByAPId?.invoke(apId)?.uid }
+ .mapNotNull { apId -> appListsRepository.getApp(apId)?.uid }
.toSet()
}
private fun refreshAppUidTrackersWhiteList() {
trackersWhitelistByUid = trackersWhitelistByApp.mapNotNull { (apId, value) ->
- getAppByAPId?.invoke(apId)?.uid?.let { uid ->
+ appListsRepository.getApp(apId)?.uid?.let { uid ->
uid to value
}
}.toMap()
@@ -190,9 +180,7 @@ class WhitelistRepository private constructor(context: Context) {
}
fun getWhiteListedApp(): List<ApplicationDescription> {
- return getAppByAPId?.let {
- appsWhitelist.mapNotNull(it)
- } ?: emptyList()
+ return appsWhitelist.mapNotNull(appListsRepository::getApp)
}
fun getWhiteListForApp(app: ApplicationDescription): List<String> {
diff --git a/trackers/src/main/java/foundation/e/privacymodules/trackers/api/Tracker.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/entities/Tracker.kt
index 2da5b16..5c31294 100644
--- a/trackers/src/main/java/foundation/e/privacymodules/trackers/api/Tracker.kt
+++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/entities/Tracker.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package foundation.e.privacymodules.trackers.api
+package foundation.e.advancedprivacy.trackers.domain.entities
/**
* Describe a tracker.
diff --git a/trackers/src/main/java/foundation/e/privacymodules/trackers/DNSBlockerRunnable.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/DNSBlocker.kt
index 44793a4..fb08910 100644
--- a/trackers/src/main/java/foundation/e/privacymodules/trackers/DNSBlockerRunnable.kt
+++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/DNSBlocker.kt
@@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package foundation.e.privacymodules.trackers
+package foundation.e.advancedprivacy.trackers.domain.usecases
import android.content.Context
import android.content.pm.PackageManager
@@ -24,40 +24,38 @@ import android.net.LocalServerSocket
import android.system.ErrnoException
import android.system.Os
import android.system.OsConstants
-import android.util.Log
-import foundation.e.privacymodules.trackers.data.TrackersRepository
-import foundation.e.privacymodules.trackers.data.WhitelistRepository
+import foundation.e.advancedprivacy.core.utils.runSuspendCatching
+import foundation.e.advancedprivacy.trackers.data.TrackersRepository
+import foundation.e.advancedprivacy.trackers.data.WhitelistRepository
+import kotlinx.coroutines.CancellationException
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.isActive
+import kotlinx.coroutines.launch
+import timber.log.Timber
import java.io.BufferedReader
-import java.io.IOException
import java.io.InputStreamReader
import java.io.PrintWriter
-class DNSBlockerRunnable(
+class DNSBlocker(
context: Context,
- private val trackersLogger: TrackersLogger,
+ val trackersLogger: TrackersLogger,
private val trackersRepository: TrackersRepository,
private val whitelistRepository: WhitelistRepository
-) : Runnable {
- var resolverReceiver: LocalServerSocket? = null
- var stopped = false
+) {
+ private var resolverReceiver: LocalServerSocket? = null
private var eBrowserAppUid = -1
companion object {
private const val SOCKET_NAME = "foundation.e.advancedprivacy"
private const val E_BROWSER_DOT_SERVER = "chrome.cloudflare-dns.com"
- private const val TAG = "DNSBlockerRunnable"
}
init {
initEBrowserDoTFix(context)
}
- @Synchronized
- fun stop() {
- stopped = true
- closeSocket()
- }
-
private fun closeSocket() {
// Known bug and workaround that LocalServerSocket::close is not working well
// https://issuetracker.google.com/issues/36945762
@@ -68,29 +66,29 @@ class DNSBlockerRunnable(
resolverReceiver = null
} catch (e: ErrnoException) {
if (e.errno != OsConstants.EBADF) {
- Log.w(TAG, "Socket already closed")
+ Timber.w("Socket already closed")
} else {
- Log.e(TAG, "Exception: cannot close DNS port on stop $SOCKET_NAME !", e)
+ Timber.e(e, "Exception: cannot close DNS port on stop $SOCKET_NAME !")
}
} catch (e: Exception) {
- Log.e(TAG, "Exception: cannot close DNS port on stop $SOCKET_NAME !", e)
+ Timber.e(e, "Exception: cannot close DNS port on stop $SOCKET_NAME !")
}
}
}
- override fun run() {
- val resolverReceiver = try {
+ fun listenJob(scope: CoroutineScope): Job = scope.launch(Dispatchers.IO) {
+ val resolverReceiver = runSuspendCatching {
LocalServerSocket(SOCKET_NAME)
- } catch (eio: IOException) {
- Log.e(TAG, "Exception:Cannot open DNS port $SOCKET_NAME !", eio)
- return
+ }.getOrElse {
+ Timber.e(it, "Exception: cannot open DNS port on $SOCKET_NAME")
+ return@launch
}
- this.resolverReceiver = resolverReceiver
- Log.d(TAG, "DNSFilterProxy running on port $SOCKET_NAME !")
+ this@DNSBlocker.resolverReceiver = resolverReceiver
+ Timber.d("DNSFilterProxy running on port $SOCKET_NAME")
- while (!stopped) {
- try {
+ while (isActive) {
+ runSuspendCatching {
val socket = resolverReceiver.accept()
val reader = BufferedReader(InputStreamReader(socket.inputStream))
val line = reader.readLine()
@@ -114,9 +112,13 @@ class DNSBlockerRunnable(
writer.println("pass")
}
socket.close()
- // Printing bufferedreader data
- } catch (e: IOException) {
- Log.w(TAG, "Exception while listening DNS resolver", e)
+ }.onFailure {
+ if (it is CancellationException) {
+ closeSocket()
+ throw it
+ } else {
+ Timber.w(it, "Exception while listening DNS resolver")
+ }
}
}
}
@@ -126,7 +128,7 @@ class DNSBlockerRunnable(
eBrowserAppUid =
context.packageManager.getApplicationInfo("foundation.e.browser", 0).uid
} catch (e: PackageManager.NameNotFoundException) {
- Log.i(TAG, "no E Browser package found.")
+ Timber.i(e, "no E Browser package found.")
}
}
diff --git a/trackers/src/main/java/foundation/e/privacymodules/trackers/data/StatsRepository.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/StatisticsUseCase.kt
index 8f02adb..55efeb9 100644
--- a/trackers/src/main/java/foundation/e/privacymodules/trackers/data/StatsRepository.kt
+++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/StatisticsUseCase.kt
@@ -16,46 +16,27 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package foundation.e.privacymodules.trackers.data
-
-import android.content.Context
-import foundation.e.privacymodules.permissions.data.ApplicationDescription
-import foundation.e.privacymodules.trackers.api.Tracker
+package foundation.e.advancedprivacy.trackers.domain.usecases
+
+import foundation.e.advancedprivacy.data.repositories.AppListsRepository
+import foundation.e.advancedprivacy.domain.entities.ApplicationDescription
+import foundation.e.advancedprivacy.trackers.data.StatsDatabase
+import foundation.e.advancedprivacy.trackers.domain.entities.Tracker
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.SharedFlow
import java.time.temporal.TemporalUnit
-class StatsRepository private constructor(context: Context) {
- private val database: StatsDatabase
- private var newDataCallback: (() -> Unit)? = null
- private var getAppByUid: ((Int) -> ApplicationDescription?)? = null
- private var getAppByAPId: ((String) -> ApplicationDescription?)? = null
-
- companion object {
- private var instance: StatsRepository? = null
- fun getInstance(context: Context): StatsRepository {
- return instance ?: StatsRepository(context).apply { instance = this }
- }
- }
-
- fun setAppGetters(
- getAppByUid: (Int) -> ApplicationDescription?,
- getAppByAPId: (String) -> ApplicationDescription?
- ) {
- this.getAppByUid = getAppByUid
- this.getAppByAPId = getAppByAPId
- }
-
- init {
- database = StatsDatabase(context)
- }
-
- fun setNewDataCallback(callback: () -> Unit) {
- newDataCallback = callback
- }
+class StatisticsUseCase(
+ private val database: StatsDatabase,
+ private val appListsRepository: AppListsRepository
+) {
+ private val _newDataAvailable = MutableSharedFlow<Unit>()
+ val newDataAvailable: SharedFlow<Unit> = _newDataAvailable
- fun logAccess(trackerId: String?, appUid: Int, blocked: Boolean) {
- getAppByUid?.invoke(appUid)?.let { app ->
+ suspend fun logAccess(trackerId: String?, appUid: Int, blocked: Boolean) {
+ appListsRepository.getApp(appUid)?.let { app ->
database.logAccess(trackerId, app.apId, blocked)
- newDataCallback?.invoke()
+ _newDataAvailable.emit(Unit)
}
}
@@ -94,12 +75,12 @@ class StatsRepository private constructor(context: Context) {
}
fun getMostLeakedApp(periodCount: Int, periodUnit: TemporalUnit): ApplicationDescription? {
- return getAppByAPId?.invoke(database.getMostLeakedAppId(periodCount, periodUnit))
+ return appListsRepository.getApp(database.getMostLeakedAppId(periodCount, periodUnit))
}
private fun <K> Map<String, K>.mapByAppIdToApp(): Map<ApplicationDescription, K> {
return entries.mapNotNull { (apId, value) ->
- getAppByAPId?.invoke(apId)?.let { it to value }
+ appListsRepository.getApp(apId)?.let { it to value }
}.toMap()
}
}
diff --git a/trackers/src/main/java/foundation/e/privacymodules/trackers/TrackersLogger.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/TrackersLogger.kt
index f3c4745..411b4ab 100644
--- a/trackers/src/main/java/foundation/e/privacymodules/trackers/TrackersLogger.kt
+++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/TrackersLogger.kt
@@ -16,49 +16,40 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package foundation.e.privacymodules.trackers
-
-import android.content.Context
-import android.util.Log
-import foundation.e.privacymodules.trackers.data.StatsRepository
+package foundation.e.advancedprivacy.trackers.domain.usecases
+
+import foundation.e.advancedprivacy.core.utils.runSuspendCatching
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.isActive
+import kotlinx.coroutines.launch
+import timber.log.Timber
import java.util.concurrent.LinkedBlockingQueue
-class TrackersLogger(context: Context) {
- private val statsRepository = StatsRepository.getInstance(context)
+class TrackersLogger(
+ private val statisticsUseCase: StatisticsUseCase,
+) {
private val queue = LinkedBlockingQueue<DetectedTracker>()
- private var stopped = false
-
- companion object {
- private const val TAG = "TrackerModule"
- }
-
- init {
- startWriteLogLoop()
- }
-
- fun stop() {
- stopped = true
- }
fun logAccess(trackerId: String?, appUid: Int, wasBlocked: Boolean) {
queue.offer(DetectedTracker(trackerId, appUid, wasBlocked))
}
- private fun startWriteLogLoop() {
- val writeLogRunner = Runnable {
- while (!stopped) {
- try {
+ fun writeLogJob(scope: CoroutineScope): Job {
+ return scope.launch(Dispatchers.IO) {
+ while (isActive) {
+ runSuspendCatching {
logAccess(queue.take())
- } catch (e: InterruptedException) {
- Log.e(TAG, "writeLogLoop detectedTrackersQueue.take() interrupted: ", e)
+ }.onFailure {
+ Timber.e(it, "writeLogLoop detectedTrackersQueue.take() interrupted: ")
}
}
}
- Thread(writeLogRunner).start()
}
- fun logAccess(detectedTracker: DetectedTracker) {
- statsRepository.logAccess(
+ private suspend fun logAccess(detectedTracker: DetectedTracker) {
+ statisticsUseCase.logAccess(
detectedTracker.trackerId,
detectedTracker.appUid,
detectedTracker.wasBlocked
diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/UpdateTrackerListUseCase.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/UpdateTrackerListUseCase.kt
new file mode 100644
index 0000000..3593dbb
--- /dev/null
+++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/domain/usecases/UpdateTrackerListUseCase.kt
@@ -0,0 +1,29 @@
+package foundation.e.advancedprivacy.trackers.domain.usecases
+
+import foundation.e.advancedprivacy.data.repositories.ETrackersApi
+import foundation.e.advancedprivacy.data.repositories.RemoteTrackersListRepository
+import foundation.e.advancedprivacy.trackers.data.TrackersRepository
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+import timber.log.Timber
+
+class UpdateTrackerListUseCase(
+ private val remoteTrackersListRepository: RemoteTrackersListRepository,
+ private val trackersRepository: TrackersRepository,
+ private val coroutineScope: CoroutineScope,
+
+) {
+ fun updateTrackers() = coroutineScope.launch {
+ update()
+ }
+
+ suspend fun update() {
+ val api = ETrackersApi.build()
+ try {
+ remoteTrackersListRepository.saveData(trackersRepository.eTrackerFile, api.trackers())
+ trackersRepository.initTrackersFile()
+ } catch (e: Exception) {
+ Timber.e("While updating trackers", e)
+ }
+ }
+}
diff --git a/trackers/src/main/java/foundation/e/privacymodules/trackers/DNSBlockerService.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/services/DNSBlockerService.kt
index c2ad16b..25539e1 100644
--- a/trackers/src/main/java/foundation/e/privacymodules/trackers/DNSBlockerService.kt
+++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/services/DNSBlockerService.kt
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2023 MURENA SAS
* Copyright (C) 2021 E FOUNDATION
*
* This program is free software: you can redistribute it and/or modify
@@ -15,28 +16,28 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package foundation.e.privacymodules.trackers
+package foundation.e.advancedprivacy.trackers.services
import android.app.Service
import android.content.Intent
import android.os.IBinder
-import android.util.Log
-import foundation.e.privacymodules.trackers.data.TrackersRepository
-import foundation.e.privacymodules.trackers.data.WhitelistRepository
+import foundation.e.advancedprivacy.trackers.domain.usecases.DNSBlocker
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.cancel
+import org.koin.java.KoinJavaComponent.get
class DNSBlockerService : Service() {
- private var trackersLogger: TrackersLogger? = null
-
companion object {
- private const val TAG = "DNSBlockerService"
- private var sDNSBlocker: DNSBlockerRunnable? = null
const val ACTION_START = "foundation.e.privacymodules.trackers.intent.action.START"
const val EXTRA_ENABLE_NOTIFICATION =
"foundation.e.privacymodules.trackers.intent.extra.ENABLED_NOTIFICATION"
}
+ private var coroutineScope = CoroutineScope(Dispatchers.IO)
+ private var dnsBlocker: DNSBlocker? = null
+
override fun onBind(intent: Intent): IBinder? {
- // TODO: Return the communication channel to the service.
throw UnsupportedOperationException("Not yet implemented")
}
@@ -52,28 +53,16 @@ class DNSBlockerService : Service() {
}
private fun start() {
- try {
- val trackersLogger = TrackersLogger(this)
- this.trackersLogger = trackersLogger
-
- sDNSBlocker = DNSBlockerRunnable(
- this,
- trackersLogger,
- TrackersRepository.getInstance(),
- WhitelistRepository.getInstance(this)
- )
- Thread(sDNSBlocker).start()
- } catch (e: Exception) {
- Log.e(TAG, "Error while starting DNSBlocker service", e)
- stop()
+ coroutineScope = CoroutineScope(Dispatchers.IO)
+ get<DNSBlocker>(DNSBlocker::class.java).apply {
+ this@DNSBlockerService.dnsBlocker = this
+ trackersLogger.writeLogJob(coroutineScope)
+ listenJob(coroutineScope)
}
}
private fun stop() {
- sDNSBlocker?.stop()
- sDNSBlocker = null
-
- trackersLogger?.stop()
- trackersLogger = null
+ kotlin.runCatching { coroutineScope.cancel() }
+ dnsBlocker = null
}
}
diff --git a/trackers/src/main/java/foundation/e/privacymodules/trackers/ForegroundStarter.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/services/ForegroundStarter.kt
index 69b4f28..a0cea43 100644
--- a/trackers/src/main/java/foundation/e/privacymodules/trackers/ForegroundStarter.kt
+++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/services/ForegroundStarter.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package foundation.e.privacymodules.trackers
+package foundation.e.advancedprivacy.trackers.services
import android.app.Notification
import android.app.NotificationChannel
diff --git a/trackers/src/main/java/foundation/e/advancedprivacy/trackers/services/UpdateTrackersWorker.kt b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/services/UpdateTrackersWorker.kt
new file mode 100644
index 0000000..50aa082
--- /dev/null
+++ b/trackers/src/main/java/foundation/e/advancedprivacy/trackers/services/UpdateTrackersWorker.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 E FOUNDATION
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package foundation.e.advancedprivacy.trackers.services
+
+import android.content.Context
+import androidx.work.Constraints
+import androidx.work.CoroutineWorker
+import androidx.work.ExistingPeriodicWorkPolicy
+import androidx.work.NetworkType
+import androidx.work.PeriodicWorkRequestBuilder
+import androidx.work.WorkManager
+import androidx.work.WorkerParameters
+import foundation.e.advancedprivacy.trackers.domain.usecases.UpdateTrackerListUseCase
+import org.koin.java.KoinJavaComponent.get
+import java.util.concurrent.TimeUnit
+
+class UpdateTrackersWorker(appContext: Context, workerParams: WorkerParameters) :
+ CoroutineWorker(appContext, workerParams) {
+
+ override suspend fun doWork(): Result {
+ val updateTrackersUsecase: UpdateTrackerListUseCase = get(UpdateTrackerListUseCase::class.java)
+
+ updateTrackersUsecase.updateTrackers()
+ return Result.success()
+ }
+
+ companion object {
+ private val constraints = Constraints.Builder()
+ .setRequiredNetworkType(NetworkType.CONNECTED)
+ .build()
+
+ fun periodicUpdate(context: Context) {
+ val request = PeriodicWorkRequestBuilder<UpdateTrackersWorker>(
+ 7, TimeUnit.DAYS
+ )
+ .setConstraints(constraints).build()
+
+ WorkManager.getInstance(context).enqueueUniquePeriodicWork(
+ UpdateTrackersWorker::class.qualifiedName ?: "",
+ ExistingPeriodicWorkPolicy.KEEP,
+ request
+ )
+ }
+ }
+}
diff --git a/trackers/src/main/java/foundation/e/privacymodules/trackers/api/BlockTrackersPrivacyModule.kt b/trackers/src/main/java/foundation/e/privacymodules/trackers/api/BlockTrackersPrivacyModule.kt
deleted file mode 100644
index 7463b22..0000000
--- a/trackers/src/main/java/foundation/e/privacymodules/trackers/api/BlockTrackersPrivacyModule.kt
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2023 MURENA SAS
- * Copyright (C) 2022 E FOUNDATION
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package foundation.e.privacymodules.trackers.api
-
-import android.content.Context
-import foundation.e.privacymodules.permissions.data.ApplicationDescription
-import foundation.e.privacymodules.trackers.data.TrackersRepository
-import foundation.e.privacymodules.trackers.data.WhitelistRepository
-
-class BlockTrackersPrivacyModule(context: Context) : IBlockTrackersPrivacyModule {
- private val mListeners = mutableListOf<IBlockTrackersPrivacyModule.Listener>()
- private val trackersRepository = TrackersRepository.getInstance()
- private val whitelistRepository = WhitelistRepository.getInstance(context)
-
- companion object {
- private var instance: BlockTrackersPrivacyModule? = null
-
- fun getInstance(context: Context): BlockTrackersPrivacyModule {
- return instance ?: BlockTrackersPrivacyModule(context).apply { instance = this }
- }
- }
-
- override fun addListener(listener: IBlockTrackersPrivacyModule.Listener) {
- mListeners.add(listener)
- }
-
- override fun clearListeners() {
- mListeners.clear()
- }
-
- override fun disableBlocking() {
- whitelistRepository.isBlockingEnabled = false
- mListeners.forEach { listener -> listener.onBlockingToggle(false) }
- }
-
- override fun enableBlocking() {
- whitelistRepository.isBlockingEnabled = true
- mListeners.forEach { listener -> listener.onBlockingToggle(true) }
- }
-
- override fun getWhiteList(app: ApplicationDescription): List<Tracker> {
- return whitelistRepository.getWhiteListForApp(app).mapNotNull {
- trackersRepository.getTracker(it)
- }
- }
-
- override fun getWhiteListedApp(): List<ApplicationDescription> {
- return whitelistRepository.getWhiteListedApp()
- }
-
- override fun isBlockingEnabled(): Boolean {
- return whitelistRepository.isBlockingEnabled
- }
-
- override fun isWhiteListEmpty(): Boolean {
- return whitelistRepository.areWhiteListEmpty()
- }
-
- override fun isWhitelisted(app: ApplicationDescription): Boolean {
- return whitelistRepository.isAppWhiteListed(app)
- }
-
- override fun removeListener(listener: IBlockTrackersPrivacyModule.Listener) {
- mListeners.remove(listener)
- }
-
- override fun setWhiteListed(
- tracker: Tracker,
- app: ApplicationDescription,
- isWhiteListed: Boolean
- ) {
- whitelistRepository.setWhiteListed(tracker, app.apId, isWhiteListed)
- }
-
- override fun setWhiteListed(app: ApplicationDescription, isWhiteListed: Boolean) {
- whitelistRepository.setWhiteListed(app.apId, isWhiteListed)
- }
-
- override fun clearWhiteList(app: ApplicationDescription) {
- whitelistRepository.clearWhiteList(app.apId)
- }
-}
diff --git a/trackers/src/main/java/foundation/e/privacymodules/trackers/api/IBlockTrackersPrivacyModule.kt b/trackers/src/main/java/foundation/e/privacymodules/trackers/api/IBlockTrackersPrivacyModule.kt
deleted file mode 100644
index 3547b8e..0000000
--- a/trackers/src/main/java/foundation/e/privacymodules/trackers/api/IBlockTrackersPrivacyModule.kt
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2023 MURENA SAS
- * Copyright (C) 2022 E FOUNDATION
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package foundation.e.privacymodules.trackers.api
-
-import foundation.e.privacymodules.permissions.data.ApplicationDescription
-
-/**
- * Manage trackers blocking and whitelisting.
- */
-interface IBlockTrackersPrivacyModule {
-
- /**
- * Get the state of the blockin module
- * @return true when blocking is enabled, false otherwise.
- */
- fun isBlockingEnabled(): Boolean
-
- /**
- * Enable blocking, using the previously configured whitelists
- */
- fun enableBlocking()
-
- /**
- * Disable blocking
- */
- fun disableBlocking()
-
- /**
- * Set or unset in whitelist the App with the specified uid.
- * @param app the ApplicationDescription of the app
- * @param isWhiteListed true, the app will appears in whitelist, false, it won't
- */
- fun setWhiteListed(app: ApplicationDescription, isWhiteListed: Boolean)
-
- /**
- * Set or unset in whitelist the specifid tracked, for the App specified by its uid.
- * @param tracker the tracker
- * @param app the ApplicationDescription of the app
- * @param isWhiteListed true, the app will appears in whitelist, false, it won't
- */
- fun setWhiteListed(tracker: Tracker, app: ApplicationDescription, isWhiteListed: Boolean)
-
- /**
- * Return true if nothing has been added to the whitelist : everything is blocked.
- */
- fun isWhiteListEmpty(): Boolean
-
- /**
- * Return the white listed App, by their UID
- */
- fun getWhiteListedApp(): List<ApplicationDescription>
-
- /**
- * Return true if the App is whitelisted for trackers blocking.
- */
- fun isWhitelisted(app: ApplicationDescription): Boolean
-
- /**
- * List the white listed trackers for an App specified by it uid
- */
- fun getWhiteList(app: ApplicationDescription): List<Tracker>
-
- fun clearWhiteList(app: ApplicationDescription)
-
- /**
- * Callback interface to get updates about the state of the Block trackers module.
- */
- interface Listener {
-
- /**
- * Called when the trackers blocking is activated or deactivated.
- * @param isBlocking true when activated, false otherwise.
- */
- fun onBlockingToggle(isBlocking: Boolean)
- }
-
- fun addListener(listener: Listener)
-
- fun removeListener(listener: Listener)
-
- fun clearListeners()
-}
diff --git a/trackers/src/main/java/foundation/e/privacymodules/trackers/api/ITrackTrackersPrivacyModule.kt b/trackers/src/main/java/foundation/e/privacymodules/trackers/api/ITrackTrackersPrivacyModule.kt
deleted file mode 100644
index 8aaed4a..0000000
--- a/trackers/src/main/java/foundation/e/privacymodules/trackers/api/ITrackTrackersPrivacyModule.kt
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2023 MURENA SAS
- * Copyright (C) 2022 E FOUNDATION
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package foundation.e.privacymodules.trackers.api
-
-import foundation.e.privacymodules.permissions.data.ApplicationDescription
-
-/**
- * Get reporting about trackers calls.
- */
-interface ITrackTrackersPrivacyModule {
-
- fun start(
- trackers: List<Tracker>,
- getAppByUid: (Int) -> ApplicationDescription?,
- getAppByAPId: (String) -> ApplicationDescription?,
- enableNotification: Boolean = true
- )
-
- /**
- * List all the trackers encountered for a specific app.
- */
- fun getTrackersForApp(app: ApplicationDescription): List<Tracker>
-
- /**
- * List all the trackers encountere trackers since "ever", for the given [appUids],
- * or all apps if [appUids] is null
- */
- fun getTrackers(apps: List<ApplicationDescription>? = null): List<Tracker>
-
- /**
- * Return the number of encountered trackers since "ever", for the given [appUids],
- * or all apps if [appUids] is null
- */
- fun getTrackersCount(): Int
-
- /**
- * Return the number of encountere trackers since "ever", for each app uid.
- */
- fun getTrackersCountByApp(): Map<ApplicationDescription, Int>
-
- /**
- * Return the number of encountered trackers for the last 24 hours
- */
- fun getPastDayTrackersCount(): Int
-
- /**
- * Return the number of encountered trackers for the last month
- */
- fun getPastMonthTrackersCount(): Int
-
- /**
- * Return the number of encountered trackers for the last year
- */
- fun getPastYearTrackersCount(): Int
-
- /**
- * Return number of trackers calls by hours, for the last 24hours.
- * @return list of 24 numbers of trackers calls by hours
- */
- fun getPastDayTrackersCalls(): List<Pair<Int, Int>>
-
- /**
- * Return number of trackers calls by day, for the last 30 days.
- * @return list of 30 numbers of trackers calls by day
- */
- fun getPastMonthTrackersCalls(): List<Pair<Int, Int>>
-
- /**
- * Return number of trackers calls by month, for the last 12 month.
- * @return list of 12 numbers of trackers calls by month
- */
- fun getPastYearTrackersCalls(): List<Pair<Int, Int>>
-
- fun getPastDayTrackersCallsByApps(): Map<ApplicationDescription, Pair<Int, Int>>
-
- fun getPastDayTrackersCallsForApp(app: ApplicationDescription): Pair<Int, Int>
-
- fun getPastDayMostLeakedApp(): ApplicationDescription?
-
- interface Listener {
-
- /**
- * Called when a new tracker attempt is logged. Consumer may choose to call other methods
- * to refresh the data.
- */
- fun onNewData()
- }
-
- fun addListener(listener: Listener)
-
- fun removeListener(listener: Listener)
-
- fun clearListeners()
-}
diff --git a/trackers/src/main/java/foundation/e/privacymodules/trackers/api/TrackTrackersPrivacyModule.kt b/trackers/src/main/java/foundation/e/privacymodules/trackers/api/TrackTrackersPrivacyModule.kt
deleted file mode 100644
index 5fc5b6b..0000000
--- a/trackers/src/main/java/foundation/e/privacymodules/trackers/api/TrackTrackersPrivacyModule.kt
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2023 MURENA SAS
- * Copyright (C) 2021 E FOUNDATION
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package foundation.e.privacymodules.trackers.api
-
-import android.content.Context
-import android.content.Intent
-import foundation.e.privacymodules.permissions.data.ApplicationDescription
-import foundation.e.privacymodules.trackers.DNSBlockerService
-import foundation.e.privacymodules.trackers.data.StatsRepository
-import foundation.e.privacymodules.trackers.data.TrackersRepository
-import foundation.e.privacymodules.trackers.data.WhitelistRepository
-import java.time.temporal.ChronoUnit
-
-class TrackTrackersPrivacyModule(private val context: Context) : ITrackTrackersPrivacyModule {
- private val statsRepository = StatsRepository.getInstance(context)
- private val listeners: MutableList<ITrackTrackersPrivacyModule.Listener> = mutableListOf()
-
- companion object {
- private var instance: TrackTrackersPrivacyModule? = null
-
- fun getInstance(context: Context): TrackTrackersPrivacyModule {
- return instance ?: TrackTrackersPrivacyModule(context).apply { instance = this }
- }
- }
-
- init {
- statsRepository.setNewDataCallback {
- listeners.forEach { listener -> listener.onNewData() }
- }
- }
-
- override fun start(
- trackers: List<Tracker>,
- getAppByUid: (Int) -> ApplicationDescription?,
- getAppByAPId: (String) -> ApplicationDescription?,
- enableNotification: Boolean
- ) {
- TrackersRepository.getInstance().setTrackersList(trackers)
- StatsRepository.getInstance(context).setAppGetters(getAppByUid, getAppByAPId)
- WhitelistRepository.getInstance(context).setAppGetters(context, getAppByAPId, getAppByUid)
- val intent = Intent(context, DNSBlockerService::class.java)
- intent.action = DNSBlockerService.ACTION_START
- intent.putExtra(DNSBlockerService.EXTRA_ENABLE_NOTIFICATION, enableNotification)
- context.startService(intent)
- }
-
- override fun getPastDayTrackersCalls(): List<Pair<Int, Int>> {
- return statsRepository.getTrackersCallsOnPeriod(24, ChronoUnit.HOURS)
- }
-
- override fun getPastMonthTrackersCalls(): List<Pair<Int, Int>> {
- return statsRepository.getTrackersCallsOnPeriod(30, ChronoUnit.DAYS)
- }
-
- override fun getPastYearTrackersCalls(): List<Pair<Int, Int>> {
- return statsRepository.getTrackersCallsOnPeriod(12, ChronoUnit.MONTHS)
- }
-
- override fun getTrackersCount(): Int {
- return statsRepository.getContactedTrackersCount()
- }
-
- override fun getTrackersCountByApp(): Map<ApplicationDescription, Int> {
- return statsRepository.getContactedTrackersCountByApp()
- }
-
- override fun getTrackersForApp(app: ApplicationDescription): List<Tracker> {
- return statsRepository.getTrackers(listOf(app))
- }
-
- override fun getTrackers(apps: List<ApplicationDescription>?): List<Tracker> {
- return statsRepository.getTrackers(apps)
- }
-
- override fun getPastDayTrackersCount(): Int {
- return statsRepository.getActiveTrackersByPeriod(24, ChronoUnit.HOURS)
- }
-
- override fun getPastMonthTrackersCount(): Int {
- return statsRepository.getActiveTrackersByPeriod(30, ChronoUnit.DAYS)
- }
-
- override fun getPastYearTrackersCount(): Int {
- return statsRepository.getActiveTrackersByPeriod(12, ChronoUnit.MONTHS)
- }
-
- override fun getPastDayMostLeakedApp(): ApplicationDescription? {
- return statsRepository.getMostLeakedApp(24, ChronoUnit.HOURS)
- }
-
- override fun getPastDayTrackersCallsByApps(): Map<ApplicationDescription, Pair<Int, Int>> {
- return statsRepository.getCallsByApps(24, ChronoUnit.HOURS)
- }
-
- override fun getPastDayTrackersCallsForApp(app: ApplicationDescription): Pair<Int, Int> {
- return statsRepository.getCalls(app, 24, ChronoUnit.HOURS)
- }
-
- override fun addListener(listener: ITrackTrackersPrivacyModule.Listener) {
- listeners.add(listener)
- }
-
- override fun removeListener(listener: ITrackTrackersPrivacyModule.Listener) {
- listeners.remove(listener)
- }
-
- override fun clearListeners() {
- listeners.clear()
- }
-}
diff --git a/trackers/src/main/java/foundation/e/privacymodules/trackers/data/TrackersRepository.kt b/trackers/src/main/java/foundation/e/privacymodules/trackers/data/TrackersRepository.kt
deleted file mode 100644
index 994bccf..0000000
--- a/trackers/src/main/java/foundation/e/privacymodules/trackers/data/TrackersRepository.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2022 E FOUNDATION
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package foundation.e.privacymodules.trackers.data
-
-import foundation.e.privacymodules.trackers.api.Tracker
-
-class TrackersRepository private constructor() {
- private var trackersById: Map<String, Tracker> = HashMap()
- private var hostnameToId: Map<String, String> = HashMap()
-
- companion object {
- private var instance: TrackersRepository? = null
- fun getInstance(): TrackersRepository {
- return instance ?: TrackersRepository().apply { instance = this }
- }
- }
-
- fun setTrackersList(list: List<Tracker>) {
- val trackersById: MutableMap<String, Tracker> = HashMap()
- val hostnameToId: MutableMap<String, String> = HashMap()
- list.forEach { tracker ->
- trackersById[tracker.id] = tracker
- for (hostname in tracker.hostnames) {
- hostnameToId[hostname] = tracker.id
- }
- }
- this.trackersById = trackersById
- this.hostnameToId = hostnameToId
- }
-
- fun isTracker(hostname: String?): Boolean {
- return hostnameToId.containsKey(hostname)
- }
-
- fun getTrackerId(hostname: String?): String? {
- return hostnameToId[hostname]
- }
-
- fun getTracker(id: String?): Tracker? {
- return trackersById[id]
- }
-}