Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a79141bb authored by Fahim M. Choudhury's avatar Fahim M. Choudhury
Browse files

Merge branch '8251-block-store-apps-parental-control' into 'main'

feat: block installation of third-party store apps when parental control is active

See merge request !495
parents ed4238a1 f37e5423
Loading
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
/*
 * Apps  Quickly and easily install Android apps onto your device!
 * Copyright (C) 2022  E FOUNDATION
 * Copyright (C) 2022-2024 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
@@ -14,6 +13,7 @@
 *
 * 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.apps.data.blockedApps
@@ -22,5 +22,6 @@ import com.google.gson.annotations.SerializedName

data class AppWarningInfo(
    @SerializedName("not_working_apps") val notWorkingApps: List<String>,
    @SerializedName("zero_privacy_apps") val zeroPrivacyApps: List<String>
    @SerializedName("zero_privacy_apps") val zeroPrivacyApps: List<String>,
    @SerializedName("third_party_store_apps") val thirdPartyStoreApps: List<String> = emptyList()
)
+7 −3
Original line number Diff line number Diff line
/*
 * Apps  Quickly and easily install Android apps onto your device!
 * Copyright (C) 2022  E FOUNDATION
 * Copyright (C) 2022-2024 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
@@ -14,6 +13,7 @@
 *
 * 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.apps.data.blockedApps

@@ -53,6 +53,10 @@ class BlockedAppRepository @Inject constructor(
    fun isPrivacyScoreZero(packageName: String) =
        blockedAppInfoList?.zeroPrivacyApps?.contains(packageName) ?: false

    fun isThirdPartyStoreApp(packageName: String): Boolean {
        return blockedAppInfoList?.thirdPartyStoreApps?.contains(packageName) ?: false
    }

    suspend fun fetchUpdateOfAppWarningList(): Boolean =
        suspendCancellableCoroutine { continuation ->
            downloadManager.downloadFileInCache(
@@ -78,7 +82,7 @@ class BlockedAppRepository @Inject constructor(
            gson.fromJson(blockedAppInfoJson, AppWarningInfo::class.java)
        } catch (exception: Exception) {
            Timber.e(exception.localizedMessage ?: "", exception)
            AppWarningInfo(listOf(), listOf())
            AppWarningInfo(listOf(), listOf(), listOf())
        }
    }
}
+12 −3
Original line number Diff line number Diff line
@@ -21,13 +21,14 @@ package foundation.e.apps.domain
import com.aurora.gplayapi.data.models.ContentRating
import foundation.e.apps.data.ResultSupreme
import foundation.e.apps.data.application.apps.AppsApi
import foundation.e.apps.data.parentalcontrol.Age
import foundation.e.apps.data.parentalcontrol.ParentalControlRepository
import foundation.e.apps.data.blockedApps.BlockedAppRepository
import foundation.e.apps.data.enums.Origin
import foundation.e.apps.data.enums.Type
import foundation.e.apps.data.install.models.AppInstall
import foundation.e.apps.data.parentalcontrol.fdroid.FDroidAntiFeatureRepository
import foundation.e.apps.data.parentalcontrol.Age
import foundation.e.apps.data.parentalcontrol.ContentRatingDao
import foundation.e.apps.data.parentalcontrol.ParentalControlRepository
import foundation.e.apps.data.parentalcontrol.fdroid.FDroidAntiFeatureRepository
import foundation.e.apps.data.parentalcontrol.googleplay.GPlayContentRatingGroup
import foundation.e.apps.data.parentalcontrol.googleplay.GPlayContentRatingRepository
import foundation.e.apps.domain.model.ContentRatingValidity
@@ -38,6 +39,7 @@ class ValidateAppAgeLimitUseCase @Inject constructor(
    private val gPlayContentRatingRepository: GPlayContentRatingRepository,
    private val fDroidAntiFeatureRepository: FDroidAntiFeatureRepository,
    private val parentalControlRepository: ParentalControlRepository,
    private val blockedAppRepository: BlockedAppRepository,
    private val appsApi: AppsApi,
    private val contentRatingDao: ContentRatingDao,
) {
@@ -60,7 +62,10 @@ class ValidateAppAgeLimitUseCase @Inject constructor(
                data = ContentRatingValidity(true)
            )

            isThirdPartyStoreApp(app) -> ResultSupreme.Success(data = ContentRatingValidity(false))

            isKnownNsfwApp(app) -> ResultSupreme.Success(data = ContentRatingValidity(false))

            isCleanApkApp(app) -> ResultSupreme.Success(
                data = ContentRatingValidity(isValid = !isNsfwAppByCleanApkApi(app))
            )
@@ -74,6 +79,10 @@ class ValidateAppAgeLimitUseCase @Inject constructor(
        }
    }

    private fun isThirdPartyStoreApp(app: AppInstall): Boolean {
        return blockedAppRepository.isThirdPartyStoreApp(app.packageName)
    }

    private fun isGitlabApp(app: AppInstall): Boolean {
        return app.origin == Origin.GITLAB_RELEASES
    }
+11 −2
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import foundation.e.apps.contract.ParentalControlContract.PATH_BLOCKLIST
import foundation.e.apps.contract.ParentalControlContract.PATH_LOGIN_TYPE
import foundation.e.apps.contract.ParentalControlContract.getAppLoungeProviderAuthority
import foundation.e.apps.data.ResultSupreme
import foundation.e.apps.data.blockedApps.BlockedAppRepository
import foundation.e.apps.data.enums.Origin
import foundation.e.apps.data.install.models.AppInstall
import foundation.e.apps.data.login.AuthenticatorRepository
@@ -73,6 +74,7 @@ class AgeRatingProvider : ContentProvider() {
        fun provideDataStoreManager(): DataStoreManager
        fun provideNotificationManager(): NotificationManager
        fun provideContentRatingDao(): ContentRatingDao
        fun provideBlockedAppRepository(): BlockedAppRepository
    }

    companion object {
@@ -88,6 +90,7 @@ class AgeRatingProvider : ContentProvider() {
    private lateinit var dataStoreManager: DataStoreManager
    private lateinit var notificationManager: NotificationManager
    private lateinit var contentRatingDao: ContentRatingDao
    private lateinit var blockedAppRepository: BlockedAppRepository

    private enum class UriCode(val code: Int) {
        LoginType(1),
@@ -228,7 +231,7 @@ class AgeRatingProvider : ContentProvider() {
        )
    }

    private suspend fun isAppValidRegardingNSWF(packageName: String): Boolean {
    private suspend fun isAppValidRegardingNSFW(packageName: String): Boolean {
        val fakeAppInstall = AppInstall(
            packageName = packageName,
            origin = Origin.CLEANAPK,
@@ -241,12 +244,17 @@ class AgeRatingProvider : ContentProvider() {
        return when {
            validateAppAgeLimitUseCase.isParentalControlDisabled() -> true
            !isInitialized() -> false
            !isAppValidRegardingNSWF(packageName) -> false
            isThirdPartyStoreApp(packageName) -> false
            !isAppValidRegardingNSFW(packageName) -> false
            isAppValidRegardingAge(packageName) == false -> false
            else -> true
        }
    }

    private fun isThirdPartyStoreApp(packageName: String): Boolean {
        return blockedAppRepository.isThirdPartyStoreApp(packageName)
    }

    private suspend fun compileAppBlockList(
        cursor: MatrixCursor,
        packageNames: List<String>,
@@ -302,6 +310,7 @@ class AgeRatingProvider : ContentProvider() {
        dataStoreManager = hiltEntryPoint.provideDataStoreManager()
        notificationManager = hiltEntryPoint.provideNotificationManager()
        contentRatingDao = hiltEntryPoint.provideContentRatingDao()
        blockedAppRepository = hiltEntryPoint.provideBlockedAppRepository()

        return true
    }