Commit 15867e6c authored by Tamas Szentpeteri's avatar Tamas Szentpeteri
Browse files

Backed out changeset 7ac962179505 (bug 1811563) for causing linting failures...

Backed out changeset 7ac962179505 (bug 1811563) for causing linting failures on AddonPermissionsScreen.kt. CLOSED TREE
parent add5221d
Loading
Loading
Loading
Loading
+0 −69
Original line number Diff line number Diff line
@@ -125,19 +125,6 @@ data class Addon(
        val granted: Boolean,
    ) : Parcelable

    /**
     * Localized permission from [Permission]
     *
     * @property localizedName The localized name of the permission to show in the UI.
     * @property permission The [Permission] that was localized.
     */
    @SuppressLint("ParcelCreator")
    @Parcelize
    data class LocalizedPermission(
        val localizedName: String,
        val permission: Permission,
    ) : Parcelable

    /**
     * Returns a list of id resources per each item on the [Addon.permissions] list.
     * Holds the state of the installed web extension of this add-on.
@@ -228,14 +215,6 @@ data class Addon(
        return localizePermissions(permissions, context)
    }

    /**
     * Returns a [LocalizedPermission] list of the optional permissions.
     * @param context Context for resource lookup
     */
    fun translateOptionalPermissions(context: Context): List<LocalizedPermission> {
        return localizeOptionalPermissions(optionalPermissions, context)
    }

    /**
     * Returns whether or not this [Addon] is currently installed.
     */
@@ -354,49 +333,6 @@ data class Addon(
            return localizedNormalPermissions + localizedUrlAccessPermissions
        }

        /**
         * Takes a list of optional permissions and returns the list of [LocalizedPermission].
         *
         * @param optionalPermissions The list of optional permissions
         * @param context The context for resource lookup
         */
        fun localizeOptionalPermissions(
            optionalPermissions: List<Permission>,
            context: Context,
        ): List<LocalizedPermission> {
            var allUrlAccessPermissionFound = false
            val notFoundPermissions = mutableListOf<Permission>()
            val localizedURLAccessPermissions = mutableListOf<LocalizedPermission>()

            val localizedOptionalPermissions: List<LocalizedPermission> = optionalPermissions.mapNotNull {
                val resourceId = permissionToTranslation[it.name]
                if (resourceId != null) {
                    if (resourceId.isAllURLsPermission()) allUrlAccessPermissionFound = true
                    LocalizedPermission(context.getString(resourceId), it)
                } else {
                    notFoundPermissions.add(it)
                    null
                }
            }

            if (!allUrlAccessPermissionFound && notFoundPermissions.isNotEmpty()) {
                notFoundPermissions.mapNotNullTo(localizedURLAccessPermissions) { permission ->
                    when (val localizedResourceId = localizeURLAccessPermission(permission.name)) {
                        null -> {
                            // Hide if we can't find a string resource to localize the permission
                            null
                        }
                        else -> {
                            val localizedName = context.getString(localizedResourceId)
                            LocalizedPermission(localizedName, permission)
                        }
                    }
                }
            }

            return localizedOptionalPermissions + localizedURLAccessPermissions
        }

        /**
         * Creates an [Addon] object from a [WebExtension] one. The resulting object might have an installed state when
         * the second method's argument is used.
@@ -581,11 +517,6 @@ data class Addon(
            return this == R.string.mozac_feature_addons_permissions_all_urls_description
        }

        fun Permission.isAllURLsPermission(): Boolean {
            return permissionToTranslation[name]?.isAllURLsPermission()
                ?: (localizeURLAccessPermission(name)?.isAllURLsPermission() == true)
        }

        internal fun localizeURLAccessPermission(urlAccess: String): Int? {
            val uri = urlAccess.toUri()
            val host = (uri.host ?: "").trim()
+0 −22
Original line number Diff line number Diff line
@@ -9,7 +9,6 @@ import mozilla.components.concept.engine.webextension.DisabledFlags
import mozilla.components.concept.engine.webextension.Incognito
import mozilla.components.concept.engine.webextension.Metadata
import mozilla.components.concept.engine.webextension.WebExtension
import mozilla.components.feature.addons.Addon.Companion.localizeOptionalPermissions
import mozilla.components.support.test.mock
import mozilla.components.support.test.robolectric.testContext
import mozilla.components.support.test.whenever
@@ -351,27 +350,6 @@ class AddonTest {
        }
    }

    @Test
    fun `localizeOptionalPermissions - should provide LocalizedPermission list`() {
        val expectedLocalizedPermissions = listOf(
            Addon.LocalizedPermission(testContext.getString(R.string.mozac_feature_addons_permissions_all_urls_description), Addon.Permission("<all_urls>", false)),
            Addon.LocalizedPermission(testContext.getString(R.string.mozac_feature_addons_permissions_web_navigation_description), Addon.Permission("webNavigation", false)),
            Addon.LocalizedPermission(testContext.getString(R.string.mozac_feature_addons_permissions_clipboard_read_description), Addon.Permission("clipboardRead", false)),
            Addon.LocalizedPermission(testContext.getString(R.string.mozac_feature_addons_permissions_clipboard_write_description), Addon.Permission("clipboardWrite", false)),
        )

        val permissions = listOf(
            Addon.Permission("<all_urls>", false),
            Addon.Permission("webNavigation", false),
            Addon.Permission("clipboardRead", false),
            Addon.Permission("clipboardWrite", false),
        )

        val localizedResult = localizeOptionalPermissions(permissions, testContext)

        assertEquals(expectedLocalizedPermissions, localizedResult)
    }

    @Test
    fun `newFromWebExtension - must return an Addon instance`() {
        val version = "1.2.3"
+60 −0
Original line number Diff line number Diff line
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.fenix.addons

import android.net.Uri
import androidx.core.net.toUri
import androidx.recyclerview.widget.LinearLayoutManager
import mozilla.components.feature.addons.Addon
import mozilla.components.feature.addons.ui.AddonPermissionsAdapter
import org.mozilla.fenix.R
import org.mozilla.fenix.databinding.FragmentAddOnPermissionsBinding
import org.mozilla.fenix.theme.ThemeManager

interface AddonPermissionsDetailsInteractor {

    /**
     * Open the given siteUrl in the browser.
     */
    fun openWebsite(addonSiteUrl: Uri)
}

/**
 * Shows the permission details of an add-on.
 */
class AddonPermissionDetailsBindingDelegate(
    val binding: FragmentAddOnPermissionsBinding,
    private val interactor: AddonPermissionsDetailsInteractor,
) {

    fun bind(addon: Addon) {
        bindPermissions(addon)
        bindLearnMore()
    }

    private fun bindPermissions(addon: Addon) {
        binding.addOnsPermissions.apply {
            layoutManager = LinearLayoutManager(context)
            val sortedPermissions = addon.translatePermissions(context).sorted()
            adapter = AddonPermissionsAdapter(
                sortedPermissions,
                style = AddonPermissionsAdapter.Style(
                    ThemeManager.resolveAttribute(R.attr.textPrimary, context),
                ),
            )
        }
    }

    private fun bindLearnMore() {
        binding.learnMoreLabel.setOnClickListener {
            interactor.openWebsite(LEARN_MORE_URL.toUri())
        }
    }

    private companion object {
        const val LEARN_MORE_URL =
            "https://support.mozilla.org/kb/permission-request-messages-firefox-extensions"
    }
}
+18 −145
Original line number Diff line number Diff line
@@ -4,172 +4,45 @@

package org.mozilla.fenix.addons

import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.navArgs
import mozilla.components.feature.addons.Addon
import mozilla.components.feature.addons.Addon.Companion.isAllURLsPermission
import mozilla.components.feature.addons.ui.translateName
import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.addons.ui.AddonPermissionsScreen
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.R
import org.mozilla.fenix.databinding.FragmentAddOnPermissionsBinding
import org.mozilla.fenix.ext.showToolbar
import org.mozilla.fenix.theme.FirefoxTheme

data class AddonPermissionsUpdateRequest(
    val optionalPermissions: List<String> = emptyList(),
    val originPermissions: List<String> = emptyList(),
)

/**
 * A fragment to show and allow a user to change permissions for an addon.
 * A fragment to show the permissions of an add-on.
 */
class AddonPermissionsDetailsFragment : Fragment() {
class AddonPermissionsDetailsFragment :
    Fragment(R.layout.fragment_add_on_permissions),
    AddonPermissionsDetailsInteractor {

    private val args by navArgs<AddonPermissionsDetailsFragmentArgs>()

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?,
    ): View = ComposeView(requireContext()).apply {
        setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)

        setContent {
            val optionalPermissions = rememberSaveable {
                mutableStateOf(args.addon.translateOptionalPermissions(requireContext()))
            }

            val originPermissions = rememberSaveable {
                mutableStateOf(
                    args.addon.optionalOrigins
                        .map {
                            Addon.LocalizedPermission(it.name, it)
                        },
                )
            }

            // Note: Even if <all_urls> is in optionalPermissions of the extension manifest, it is found in
            // originPermissions of the Addon
            val allSitesHostPermissionsList = rememberSaveable {
                mutableStateOf(
                    args.addon.optionalOrigins.getAllSitesPermissionsList(),
                )
            }

            // Update all of the mutable states when an addon is returned from updating permissions
            val onUpdatePermissionsSuccess: (Addon) -> Unit = { updatedAddon ->
                optionalPermissions.value =
                    updatedAddon.translateOptionalPermissions(requireContext())
                originPermissions.value = updatedAddon.optionalOrigins.map {
                    Addon.LocalizedPermission(it.name, it)
                }
                allSitesHostPermissionsList.value =
                    updatedAddon.optionalOrigins.getAllSitesPermissionsList()
            }

            FirefoxTheme {
                AddonPermissionsScreen(
                    permissions = args.addon.translatePermissions(requireContext()),
                    optionalPermissions = optionalPermissions.value,
                    originPermissions = originPermissions.value,
                    isAllSitesSwitchVisible = allSitesHostPermissionsList.value.isNotEmpty(),
                    isAllSitesEnabled = allSitesHostPermissionsList.value.getOrNull(0)?.granted
                        ?: false,
                    onAddOptionalPermissions = { permissionRequest ->
                        addOptionalPermissions(permissionRequest, onUpdatePermissionsSuccess)
                    },
                    onRemoveOptionalPermissions = { permissionRequest ->
                        removeOptionalPermission(permissionRequest, onUpdatePermissionsSuccess)
                    },
                    onAddAllSitesPermissions = {
                        addOptionalPermissions(
                            AddonPermissionsUpdateRequest(
                                originPermissions = allSitesHostPermissionsList.value.map { it.name },
                            ),
                            onUpdatePermissionsSuccess,
                        )
                    },
                    onRemoveAllSitesPermissions = {
                        removeOptionalPermission(
                            AddonPermissionsUpdateRequest(
                                originPermissions = allSitesHostPermissionsList.value.map { it.name },
                            ),
                            onUpdatePermissionsSuccess,
                        )
                    },
                    onLearnMoreClick = { learnMoreUrl ->
                        openWebsite(learnMoreUrl)
                    },
                )
            }
        }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val binding = FragmentAddOnPermissionsBinding.bind(view)
        AddonPermissionDetailsBindingDelegate(binding, interactor = this).bind(args.addon)
    }

    private fun addOptionalPermissions(
        addPermissionsRequest: AddonPermissionsUpdateRequest,
        onUpdatePermissionsSuccess: (Addon) -> Unit,
    ) {
        requireContext().components.addonManager.addOptionalPermission(
            args.addon,
            addPermissionsRequest.optionalPermissions,
            addPermissionsRequest.originPermissions,
            onSuccess = {
                onUpdatePermissionsSuccess(it)
            },
            onError = {
                /** No-Op **/
            },
        )
    override fun onResume() {
        super.onResume()
        context?.let {
            showToolbar(title = args.addon.translateName(it))
        }

    private fun removeOptionalPermission(
        removePermissionsRequest: AddonPermissionsUpdateRequest,
        onUpdatePermissionsSuccess: (Addon) -> Unit,
    ) {
        requireContext().components.addonManager.removeOptionalPermission(
            args.addon,
            removePermissionsRequest.optionalPermissions,
            removePermissionsRequest.originPermissions,
            onSuccess = {
                onUpdatePermissionsSuccess(it)
            },
            onError = {
                /** No-Op **/
            },
        )
    }

    private fun openWebsite(addonSiteUrl: String) {
    override fun openWebsite(addonSiteUrl: Uri) {
        (activity as HomeActivity).openToBrowserAndLoad(
            searchTermOrURL = addonSiteUrl,
            searchTermOrURL = addonSiteUrl.toString(),
            newTab = true,
            from = BrowserDirection.FromAddonPermissionsDetailsFragment,
        )
    }

    private fun <T : List<Addon.Permission>> T.getAllSitesPermissionsList(): List<Addon.Permission> {
        return this.mapNotNull {
            if (it.isAllURLsPermission()) {
                it
            } else {
                null
            }
        }
    }

    override fun onResume() {
        super.onResume()
        context?.let {
            showToolbar(title = args.addon.translateName(it))
        }
    }
}
+0 −300

File deleted.

Preview size limit exceeded, changes collapsed.

Loading