diff options
author | Guillaume Jacquart <guillaume.jacquart@hoodbrains.com> | 2022-03-03 07:36:58 +0000 |
---|---|---|
committer | Guillaume Jacquart <guillaume.jacquart@hoodbrains.com> | 2022-03-03 07:36:58 +0000 |
commit | 6d2cce8fa6748a1aceecd71c44296955d36fcebf (patch) | |
tree | e58b397c478d8d61cfedc541ff3361692b917883 /app/src/main/java/foundation | |
parent | 72a66e8640c21683e99e4e7d866253fe205d14f0 (diff) | |
parent | 00620b4b24482c67541106b6b4584b3ff4f383ca (diff) |
Merge branch 'auto_update_trackers' into 'main'
Update trackers list each week #4595
See merge request e/privacy-central/privacycentralapp!21
Diffstat (limited to 'app/src/main/java/foundation')
7 files changed, 90 insertions, 40 deletions
diff --git a/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt b/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt index 6b4035e..639e7b4 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt @@ -50,8 +50,7 @@ import kotlinx.coroutines.GlobalScope * * TODO: Test if this implementation is leaky. */ -class DependencyContainer constructor(val app: Application) { - +class DependencyContainer(val app: Application) { val context: Context by lazy { app.applicationContext } // Drivers @@ -92,7 +91,7 @@ class DependencyContainer constructor(val app: Application) { TrackersStatisticsUseCase(trackTrackersPrivacyModule, blockTrackersPrivacyModule, appListsRepository, context.resources) } - private val trackersStateUseCase by lazy { + val trackersStateUseCase by lazy { TrackersStateUseCase(blockTrackersPrivacyModule, trackTrackersPrivacyModule, permissionsModule, localStateRepository, trackersRepository, appListsRepository, GlobalScope) } @@ -131,5 +130,7 @@ class DependencyContainer constructor(val app: Application) { trackersStateUseCase ipScramblingStateUseCase fakeLocationStateUseCase + + UpdateTrackersWorker.periodicUpdate(context) } } diff --git a/app/src/main/java/foundation/e/privacycentralapp/UpdateTrackersWorker.kt b/app/src/main/java/foundation/e/privacycentralapp/UpdateTrackersWorker.kt new file mode 100644 index 0000000..ba6bae9 --- /dev/null +++ b/app/src/main/java/foundation/e/privacycentralapp/UpdateTrackersWorker.kt @@ -0,0 +1,53 @@ +/* + * 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.privacycentralapp + +import android.content.Context +import androidx.work.CoroutineWorker +import androidx.work.ExistingPeriodicWorkPolicy +import androidx.work.PeriodicWorkRequestBuilder +import androidx.work.WorkManager +import androidx.work.WorkerParameters +import java.time.temporal.ChronoUnit + +class UpdateTrackersWorker(appContext: Context, workerParams: WorkerParameters) : + CoroutineWorker(appContext, workerParams) { + + override suspend fun doWork(): Result { + val trackersStateUseCase = (applicationContext as PrivacyCentralApplication) + .dependencyContainer.trackersStateUseCase + + trackersStateUseCase.updateTrackers() + return Result.success() + } + + companion object { + fun periodicUpdate(context: Context) { + val request = PeriodicWorkRequestBuilder<UpdateTrackersWorker>( + ChronoUnit.WEEKS.duration, + ChronoUnit.DAYS.duration + ).build() + + WorkManager.getInstance(context).enqueueUniquePeriodicWork( + UpdateTrackersWorker::class.qualifiedName ?: "", + ExistingPeriodicWorkPolicy.REPLACE, + request + ) + } + } +} diff --git a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt b/app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt index 958a536..3573d4f 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt @@ -21,6 +21,7 @@ import android.Manifest import android.content.Context import android.content.Intent import android.content.pm.ApplicationInfo +import android.content.pm.PackageManager import foundation.e.privacymodules.permissions.PermissionsPrivacyModule import foundation.e.privacymodules.permissions.data.ApplicationDescription import kotlinx.coroutines.CoroutineScope @@ -40,8 +41,10 @@ class AppListsRepository( coroutineScope.launch { val (visible, hidden) = splitVisibleToHidden(getAppsUsingInternet()) appDescriptions.emit( - visible.map { it.toApplicationDescription(withIcon = true) } - to hidden.map { it.toApplicationDescription() } + Pair( + visible.map { permissionsModule.buildApplicationDescription(it, withIcon = true) }, + hidden.map { permissionsModule.buildApplicationDescription(it, withIcon = false) }, + ) ) } return appDescriptions.map { it.first.sortedBy { app -> app.label.toString().lowercase() } } @@ -61,15 +64,18 @@ class AppListsRepository( private val pm get() = context.packageManager private val appDescriptions = MutableStateFlow( - emptyList<ApplicationDescription>() to emptyList<ApplicationDescription>() + Pair( + emptyList<ApplicationDescription>(), + emptyList<ApplicationDescription>() + ) ) private fun getAppsUsingInternet(): List<ApplicationInfo> { - return pm.getInstalledApplications(0) - .filter { - permissionsModule.getPermissions(it.packageName) - .contains(Manifest.permission.INTERNET) - } + return pm.getInstalledPackages(PackageManager.GET_PERMISSIONS).filter { + it.requestedPermissions?.contains(Manifest.permission.INTERNET) == true + }.map { + it.applicationInfo + } } private fun isNotHiddenSystemApp(app: ApplicationInfo, launcherApps: List<String>): Boolean { @@ -102,11 +108,4 @@ class AppListsRepository( acc } } - - private fun ApplicationInfo.toApplicationDescription(withIcon: Boolean = true) = ApplicationDescription( - packageName = packageName, - uid = uid, - label = pm.getApplicationLabel(this), - icon = if (withIcon) pm.getApplicationIcon(packageName) else null - ) } diff --git a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/TrackersRepository.kt b/app/src/main/java/foundation/e/privacycentralapp/data/repositories/TrackersRepository.kt index c7efa84..8216a19 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/TrackersRepository.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/data/repositories/TrackersRepository.kt @@ -20,13 +20,11 @@ package foundation.e.privacycentralapp.data.repositories import android.content.Context import android.util.Log import com.google.gson.Gson -import com.google.gson.annotations.SerializedName import foundation.e.privacymodules.trackers.Tracker import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import retrofit2.http.GET import java.io.InputStreamReader -import java.lang.Exception class TrackersRepository(private val context: Context) { @@ -37,6 +35,12 @@ class TrackersRepository(private val context: Context) { initFromAssets() } + suspend fun update() { + val api = ETrackersApi.build() + val response = api.trackers() + trackers = mapper(response) + } + private fun initFromAssets() { try { val reader = InputStreamReader(context.getAssets().open("e_trackers.json"), "UTF-8") @@ -65,8 +69,7 @@ class TrackersRepository(private val context: Context) { id = id!!, hostnames = hostnames!!.toSet(), label = name!!, - description = description, - website = website, + exodusId = exodusId ) } } @@ -75,14 +78,14 @@ interface ETrackersApi { companion object { fun build(): ETrackersApi { val retrofit = Retrofit.Builder() - .baseUrl("TODO") + .baseUrl("https://gitlab.e.foundation/e/apps/tracker-list/-/raw/main/") .addConverterFactory(GsonConverterFactory.create()) .build() return retrofit.create(ETrackersApi::class.java) } } - @GET("TODO") + @GET("list/e_trackers.json") suspend fun trackers(): ETrackersResponse data class ETrackersResponse(val trackers: List<ETracker>) { @@ -90,13 +93,7 @@ interface ETrackersApi { val id: String?, val hostnames: List<String>?, val name: String?, - - val description: String?, - @SerializedName("creation_date") val creationDate: String?, - @SerializedName("code_signature") val codeSignature: String?, - @SerializedName("network_signature") val networkSignature: String?, - val website: String?, - val categories: List<String>?, + val exodusId: String? ) } } diff --git a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStateUseCase.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStateUseCase.kt index 16a1a82..ecf2e7b 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStateUseCase.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/TrackersStateUseCase.kt @@ -26,6 +26,7 @@ import foundation.e.privacymodules.trackers.IBlockTrackersPrivacyModule import foundation.e.privacymodules.trackers.ITrackTrackersPrivacyModule import foundation.e.privacymodules.trackers.Tracker import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.collect @@ -38,7 +39,7 @@ class TrackersStateUseCase( private val localStateRepository: LocalStateRepository, private val trackersRepository: TrackersRepository, private val appListsRepository: AppListsRepository, - coroutineScope: CoroutineScope + private val coroutineScope: CoroutineScope ) { private val _areAllTrackersBlocked = MutableStateFlow( @@ -106,4 +107,9 @@ class TrackersStateUseCase( updateAllTrackersBlockedState() } + + fun updateTrackers() = coroutineScope.launch { + trackersRepository.update() + trackersPrivacyModule.start(trackersRepository.trackers, enableNotification = false) + } } diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFeature.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFeature.kt index b35fbca..790a5a0 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFeature.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/AppTrackersFeature.kt @@ -192,7 +192,7 @@ class AppTrackersFeature( } is Action.ClickTracker -> { flowOf( - action.tracker.getExodusId()?.let { + action.tracker.exodusId?.let { try { Effect.OpenUrlEffect(Uri.parse(exodusBaseUrl + it)) } catch (e: Exception) { @@ -226,9 +226,3 @@ class AppTrackersFeature( ) } } - -fun Tracker.getExodusId(): String? { - return if (id.startsWith("exodus_")) { - id.substringAfter("exodus_") - } else null -} diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/ToggleTrackersAdapter.kt b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/ToggleTrackersAdapter.kt index 82f2d2c..e77b61f 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/ToggleTrackersAdapter.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/trackers/apptrackers/ToggleTrackersAdapter.kt @@ -46,7 +46,7 @@ class ToggleTrackersAdapter( fun bind(item: Pair<Tracker, Boolean>, isEnabled: Boolean) { val text = item.first.label - if (item.first.website != null) { + if (item.first.exodusId != null) { title.setTextColor(ContextCompat.getColor(title.context, R.color.accent)) val spannable = SpannableString(text) spannable.setSpan(UnderlineSpan(), 0, spannable.length, 0) |