aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/main/java/foundation/e/privacycentralapp/data
diff options
context:
space:
mode:
authorGuillaume Jacquart <guillaume.jacquart@hoodbrains.com>2023-05-02 21:25:17 +0200
committerGuillaume Jacquart <guillaume.jacquart@hoodbrains.com>2023-05-02 22:00:35 +0200
commita8874167f663885f2d3371801cf03681576ac817 (patch)
tree5be07b8768142efeade536d4135f2250c1ac9071 /app/src/main/java/foundation/e/privacycentralapp/data
parenta0ee04ea9dbc0802c828afdf660eb37dc6fa350f (diff)
downloadadvanced-privacy-a8874167f663885f2d3371801cf03681576ac817.tar.gz
1200: rename everything to AdvancedPrivacy
Diffstat (limited to 'app/src/main/java/foundation/e/privacycentralapp/data')
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt281
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/data/repositories/CityDataSource.kt46
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/data/repositories/LocalStateRepository.kt116
-rw-r--r--app/src/main/java/foundation/e/privacycentralapp/data/repositories/TrackersRepository.kt129
4 files changed, 0 insertions, 572 deletions
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
deleted file mode 100644
index a4f7487..0000000
--- a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/AppListsRepository.kt
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (C) 2022 E FOUNDATION, 2022 - 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.privacycentralapp.data.repositories
-
-import android.Manifest
-import android.content.Context
-import android.content.Intent
-import android.content.pm.ApplicationInfo
-import android.content.pm.PackageInfo
-import foundation.e.privacycentralapp.R
-import foundation.e.privacymodules.permissions.PermissionsPrivacyModule
-import foundation.e.privacymodules.permissions.data.ApplicationDescription
-import foundation.e.privacymodules.permissions.data.ProfileType
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
-
-class AppListsRepository(
- private val permissionsModule: PermissionsPrivacyModule,
- private val context: Context,
- private val coroutineScope: CoroutineScope
-) {
- companion object {
- private const val PNAME_SETTINGS = "com.android.settings"
- private const val PNAME_PWAPLAYER = "foundation.e.pwaplayer"
- private const val PNAME_INTENT_VERIFICATION = "com.android.statementservice"
- private const val PNAME_MICROG_SERVICES_CORE = "com.google.android.gms"
-
- val compatibiltyPNames = setOf(
- PNAME_PWAPLAYER, PNAME_INTENT_VERIFICATION, PNAME_MICROG_SERVICES_CORE
- )
- }
-
- val dummySystemApp = ApplicationDescription(
- packageName = "foundation.e.dummysystemapp",
- uid = -1,
- label = context.getString(R.string.dummy_system_app_label),
- icon = context.getDrawable(R.drawable.ic_e_app_logo),
- profileId = -1,
- profileType = ProfileType.MAIN
- )
-
- val dummyCompatibilityApp = ApplicationDescription(
- packageName = "foundation.e.dummyappscompatibilityapp",
- uid = -2,
- label = context.getString(R.string.dummy_apps_compatibility_app_label),
- icon = context.getDrawable(R.drawable.ic_apps_compatibility_components),
- profileId = -1,
- profileType = ProfileType.MAIN
- )
-
- private suspend fun fetchAppDescriptions(fetchMissingIcons: Boolean = false) {
- val launcherPackageNames = context.packageManager.queryIntentActivities(
- Intent(Intent.ACTION_MAIN, null).apply { addCategory(Intent.CATEGORY_LAUNCHER) },
- 0
- ).mapNotNull { it.activityInfo?.packageName }
-
- val visibleAppsFilter = { packageInfo: PackageInfo ->
- hasInternetPermission(packageInfo) &&
- isStandardApp(packageInfo.applicationInfo, launcherPackageNames)
- }
-
- val hiddenAppsFilter = { packageInfo: PackageInfo ->
- hasInternetPermission(packageInfo) &&
- isHiddenSystemApp(packageInfo.applicationInfo, launcherPackageNames)
- }
-
- val compatibilityAppsFilter = { packageInfo: PackageInfo ->
- packageInfo.packageName in compatibiltyPNames
- }
-
- val visibleApps = recycleIcons(
- newApps = permissionsModule.getApplications(visibleAppsFilter),
- fetchMissingIcons = fetchMissingIcons
- )
- val hiddenApps = permissionsModule.getApplications(hiddenAppsFilter)
- val compatibilityApps = permissionsModule.getApplications(compatibilityAppsFilter)
-
- updateMaps(visibleApps + hiddenApps + compatibilityApps)
-
- allProfilesAppDescriptions.emit(
- Triple(
- visibleApps + dummySystemApp + dummyCompatibilityApp,
- hiddenApps,
- compatibilityApps
- )
- )
- }
-
- private fun recycleIcons(
- newApps: List<ApplicationDescription>,
- fetchMissingIcons: Boolean
- ): List<ApplicationDescription> {
- val oldVisibleApps = allProfilesAppDescriptions.value.first
- return newApps.map { app ->
- app.copy(
- icon = oldVisibleApps.find { app.apId == it.apId }?.icon
- ?: if (fetchMissingIcons) permissionsModule.getApplicationIcon(app) else null
- )
- }
- }
-
- private fun updateMaps(apps: List<ApplicationDescription>) {
- val byUid = mutableMapOf<Int, ApplicationDescription>()
- val byApId = mutableMapOf<String, ApplicationDescription>()
- apps.forEach { app ->
- byUid[app.uid]?.run { packageName > app.packageName } == true
- if (byUid[app.uid].let { it == null || it.packageName > app.packageName }) {
- byUid[app.uid] = app
- }
-
- byApId[app.apId] = app
- }
- appsByUid = byUid
- appsByAPId = byApId
- }
-
- private var lastFetchApps = 0
- private var refreshAppJob: Job? = null
- private fun refreshAppDescriptions(fetchMissingIcons: Boolean = true, force: Boolean = false): Job? {
- if (refreshAppJob == null) {
- refreshAppJob = coroutineScope.launch(Dispatchers.IO) {
- if (force || context.packageManager.getChangedPackages(lastFetchApps) != null) {
- fetchAppDescriptions(fetchMissingIcons = fetchMissingIcons)
- if (fetchMissingIcons) {
- lastFetchApps = context.packageManager.getChangedPackages(lastFetchApps)
- ?.sequenceNumber ?: lastFetchApps
- }
-
- refreshAppJob = null
- }
- }
- }
-
- return refreshAppJob
- }
-
- fun mainProfileApps(): Flow<List<ApplicationDescription>> {
- refreshAppDescriptions()
- return allProfilesAppDescriptions.map {
- it.first.filter { app -> app.profileType == ProfileType.MAIN }
- .sortedBy { app -> app.label.toString().lowercase() }
- }
- }
-
- fun getMainProfileHiddenSystemApps(): List<ApplicationDescription> {
- return allProfilesAppDescriptions.value.second.filter { it.profileType == ProfileType.MAIN }
- }
-
- fun apps(): Flow<List<ApplicationDescription>> {
- refreshAppDescriptions()
- return allProfilesAppDescriptions.map {
- it.first.sortedBy { app -> app.label.toString().lowercase() }
- }
- }
-
- fun allApps(): Flow<List<ApplicationDescription>> {
- return allProfilesAppDescriptions.map {
- it.first + it.second + it.third
- }
- }
-
- private fun getHiddenSystemApps(): List<ApplicationDescription> {
- return allProfilesAppDescriptions.value.second
- }
-
- private fun getCompatibilityApps(): List<ApplicationDescription> {
- return allProfilesAppDescriptions.value.third
- }
-
- fun anyForHiddenApps(app: ApplicationDescription, test: (ApplicationDescription) -> Boolean): Boolean {
- return if (app == dummySystemApp) {
- getHiddenSystemApps().any { test(it) }
- } else if (app == dummyCompatibilityApp) {
- getCompatibilityApps().any { test(it) }
- } else test(app)
- }
-
- fun applyForHiddenApps(app: ApplicationDescription, action: (ApplicationDescription) -> Unit) {
- mapReduceForHiddenApps(app = app, map = action, reduce = {})
- }
-
- fun <T, R> mapReduceForHiddenApps(
- app: ApplicationDescription,
- map: (ApplicationDescription) -> T,
- reduce: (List<T>) -> R
- ): R {
- return if (app == dummySystemApp) {
- reduce(getHiddenSystemApps().map(map))
- } else if (app == dummyCompatibilityApp) {
- reduce(getCompatibilityApps().map(map))
- } else reduce(listOf(map(app)))
- }
-
- private var appsByUid = mapOf<Int, ApplicationDescription>()
- private var appsByAPId = mapOf<String, ApplicationDescription>()
-
- fun getApp(appUid: Int): ApplicationDescription? {
- return appsByUid[appUid] ?: run {
- runBlocking { refreshAppDescriptions(fetchMissingIcons = false, force = true)?.join() }
- appsByUid[appUid]
- }
- }
-
- fun getApp(apId: String): ApplicationDescription? {
- if (apId.isBlank()) return null
-
- return appsByAPId[apId] ?: run {
- runBlocking { refreshAppDescriptions(fetchMissingIcons = false, force = true)?.join() }
- appsByAPId[apId]
- }
- }
-
- private val allProfilesAppDescriptions = MutableStateFlow(
- Triple(
- emptyList<ApplicationDescription>(),
- emptyList<ApplicationDescription>(),
- emptyList<ApplicationDescription>()
- )
- )
-
- private fun hasInternetPermission(packageInfo: PackageInfo): Boolean {
- return packageInfo.requestedPermissions?.contains(Manifest.permission.INTERNET) == true
- }
-
- @Suppress("ReturnCount")
- private fun isNotHiddenSystemApp(app: ApplicationInfo, launcherApps: List<String>): Boolean {
- if (app.packageName == PNAME_SETTINGS) {
- return false
- } else if (app.packageName == PNAME_PWAPLAYER) {
- return true
- } else if (app.hasFlag(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) {
- return true
- } else if (!app.hasFlag(ApplicationInfo.FLAG_SYSTEM)) {
- return true
- } else if (launcherApps.contains(app.packageName)) {
- return true
- }
- return false
- }
-
- private fun isStandardApp(app: ApplicationInfo, launcherApps: List<String>): Boolean {
- return when {
- app.packageName == PNAME_SETTINGS -> false
- app.packageName in compatibiltyPNames -> false
- app.hasFlag(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) -> true
- !app.hasFlag(ApplicationInfo.FLAG_SYSTEM) -> true
- launcherApps.contains(app.packageName) -> true
- else -> false
- }
- }
-
- private fun isHiddenSystemApp(app: ApplicationInfo, launcherApps: List<String>): Boolean {
- return when {
- app.packageName in compatibiltyPNames -> false
- else -> !isNotHiddenSystemApp(app, launcherApps)
- }
- }
-
- private fun ApplicationInfo.hasFlag(flag: Int) = (flags and flag) == 1
-}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/CityDataSource.kt b/app/src/main/java/foundation/e/privacycentralapp/data/repositories/CityDataSource.kt
deleted file mode 100644
index d6a6a19..0000000
--- a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/CityDataSource.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.privacycentralapp.dummy
-
-object CityDataSource {
- private val BARCELONA = Pair(41.3851f, 2.1734f)
- private val BUDAPEST = Pair(47.4979f, 19.0402f)
- private val ABU_DHABI = Pair(24.4539f, 54.3773f)
- private val HYDERABAD = Pair(17.3850f, 78.4867f)
- private val QUEZON_CITY = Pair(14.6760f, 121.0437f)
- private val PARIS = Pair(48.8566f, 2.3522f)
- private val LONDON = Pair(51.5074f, 0.1278f)
- private val SHANGHAI = Pair(31.2304f, 121.4737f)
- private val MADRID = Pair(40.4168f, -3.7038f)
- private val LAHORE = Pair(31.5204f, 74.3587f)
- private val CHICAGO = Pair(41.8781f, -87.6298f)
-
- val citiesLocationsList = listOf(
- BARCELONA,
- BUDAPEST,
- ABU_DHABI,
- HYDERABAD,
- QUEZON_CITY,
- PARIS,
- LONDON,
- SHANGHAI,
- MADRID,
- LAHORE,
- CHICAGO
- )
-}
diff --git a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/LocalStateRepository.kt b/app/src/main/java/foundation/e/privacycentralapp/data/repositories/LocalStateRepository.kt
deleted file mode 100644
index ed97c94..0000000
--- a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/LocalStateRepository.kt
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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.privacycentralapp.data.repositories
-
-import android.content.Context
-import foundation.e.privacycentralapp.domain.entities.InternetPrivacyMode
-import foundation.e.privacycentralapp.domain.entities.LocationMode
-import foundation.e.privacymodules.permissions.data.ApplicationDescription
-import kotlinx.coroutines.flow.MutableSharedFlow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.SharedFlow
-import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.flow.update
-
-class LocalStateRepository(context: Context) {
- companion object {
- private const val SHARED_PREFS_FILE = "localState"
- private const val KEY_BLOCK_TRACKERS = "blockTrackers"
- private const val KEY_IP_SCRAMBLING = "ipScrambling"
- private const val KEY_FAKE_LOCATION = "fakeLocation"
- private const val KEY_FAKE_LATITUDE = "fakeLatitude"
- private const val KEY_FAKE_LONGITUDE = "fakeLongitude"
- private const val KEY_FIRST_BOOT = "firstBoot"
- private const val KEY_HIDE_WARNING_TRACKERS = "hide_warning_trackers"
- private const val KEY_HIDE_WARNING_LOCATION = "hide_warning_location"
- private const val KEY_HIDE_WARNING_IPSCRAMBLING = "hide_warning_ipscrambling"
- }
-
- private val sharedPref = context.getSharedPreferences(SHARED_PREFS_FILE, Context.MODE_PRIVATE)
-
- private val _blockTrackers = MutableStateFlow(sharedPref.getBoolean(KEY_BLOCK_TRACKERS, true))
- val blockTrackers = _blockTrackers.asStateFlow()
-
- fun setBlockTrackers(enabled: Boolean) {
- set(KEY_BLOCK_TRACKERS, enabled)
- _blockTrackers.update { enabled }
- }
-
- val areAllTrackersBlocked: MutableStateFlow<Boolean> = MutableStateFlow(false)
-
- private val _fakeLocationEnabled = MutableStateFlow(sharedPref.getBoolean(KEY_FAKE_LOCATION, false))
-
- val fakeLocationEnabled = _fakeLocationEnabled.asStateFlow()
-
- fun setFakeLocationEnabled(enabled: Boolean) {
- set(KEY_FAKE_LOCATION, enabled)
- _fakeLocationEnabled.update { enabled }
- }
-
- var fakeLocation: Pair<Float, Float>
- get() = Pair(
- // Initial default value is Quezon City
- sharedPref.getFloat(KEY_FAKE_LATITUDE, 14.6760f),
- sharedPref.getFloat(KEY_FAKE_LONGITUDE, 121.0437f)
- )
-
- set(value) {
- sharedPref.edit()
- .putFloat(KEY_FAKE_LATITUDE, value.first)
- .putFloat(KEY_FAKE_LONGITUDE, value.second)
- .apply()
- }
-
- val locationMode: MutableStateFlow<LocationMode> = MutableStateFlow(LocationMode.REAL_LOCATION)
-
- private val _ipScramblingSetting = MutableStateFlow(sharedPref.getBoolean(KEY_IP_SCRAMBLING, false))
- val ipScramblingSetting = _ipScramblingSetting.asStateFlow()
-
- fun setIpScramblingSetting(enabled: Boolean) {
- set(KEY_IP_SCRAMBLING, enabled)
- _ipScramblingSetting.update { enabled }
- }
-
- val internetPrivacyMode: MutableStateFlow<InternetPrivacyMode> = MutableStateFlow(InternetPrivacyMode.REAL_IP)
-
- private val _otherVpnRunning = MutableSharedFlow<ApplicationDescription>()
- suspend fun emitOtherVpnRunning(appDesc: ApplicationDescription) {
- _otherVpnRunning.emit(appDesc)
- }
- val otherVpnRunning: SharedFlow<ApplicationDescription> = _otherVpnRunning
-
- var firstBoot: Boolean
- get() = sharedPref.getBoolean(KEY_FIRST_BOOT, true)
- set(value) = set(KEY_FIRST_BOOT, value)
-
- var hideWarningTrackers: Boolean
- get() = sharedPref.getBoolean(KEY_HIDE_WARNING_TRACKERS, false)
- set(value) = set(KEY_HIDE_WARNING_TRACKERS, value)
-
- var hideWarningLocation: Boolean
- get() = sharedPref.getBoolean(KEY_HIDE_WARNING_LOCATION, false)
- set(value) = set(KEY_HIDE_WARNING_LOCATION, value)
-
- var hideWarningIpScrambling: Boolean
- get() = sharedPref.getBoolean(KEY_HIDE_WARNING_IPSCRAMBLING, false)
- set(value) = set(KEY_HIDE_WARNING_IPSCRAMBLING, value)
-
- private fun set(key: String, value: Boolean) {
- sharedPref.edit().putBoolean(key, value).apply()
- }
-}
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
deleted file mode 100644
index b5310e1..0000000
--- a/app/src/main/java/foundation/e/privacycentralapp/data/repositories/TrackersRepository.kt
+++ /dev/null
@@ -1,129 +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.privacycentralapp.data.repositories
-
-import android.content.Context
-import android.util.Log
-import com.google.gson.Gson
-import foundation.e.privacymodules.trackers.api.Tracker
-import retrofit2.Retrofit
-import retrofit2.converter.scalars.ScalarsConverterFactory
-import retrofit2.http.GET
-import java.io.File
-import java.io.FileInputStream
-import java.io.FileWriter
-import java.io.IOException
-import java.io.InputStreamReader
-import java.io.PrintWriter
-
-class TrackersRepository(private val context: Context) {
-
- private val eTrackerFileName = "e_trackers.json"
- private val eTrackerFile = File(context.filesDir.absolutePath, eTrackerFileName)
-
- var trackers: List<Tracker> = emptyList()
- private set
-
- init {
- initTrackersFile()
- }
-
- suspend fun update() {
- val api = ETrackersApi.build()
- saveData(eTrackerFile, api.trackers())
- initTrackersFile()
- }
-
- private 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, ETrackersApi.ETrackersResponse::class.java)
-
- trackers = mapper(trackerResponse)
-
- reader.close()
- inputStream.close()
- } catch (e: Exception) {
- Log.e("TrackersRepository", "While parsing trackers in assets", e)
- }
- }
-
- private fun mapper(response: ETrackersApi.ETrackersResponse): List<Tracker> {
- return response.trackers.mapNotNull {
- try {
- it.toTracker()
- } catch (e: Exception) {
- null
- }
- }
- }
-
- private fun ETrackersApi.ETrackersResponse.ETracker.toTracker(): Tracker {
- return Tracker(
- id = id!!,
- hostnames = hostnames!!.toSet(),
- label = name!!,
- exodusId = exodusId
- )
- }
-
- private 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) {
- e.printStackTrace()
- }
- 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
-
- data class ETrackersResponse(val trackers: List<ETracker>) {
- data class ETracker(
- val id: String?,
- val hostnames: List<String>?,
- val name: String?,
- val exodusId: String?
- )
- }
-}