Commit 270857e1 authored by MozLando's avatar MozLando
Browse files

Merge #6052



6052: Closes #6015: Deny installing add-ons if built-in permissions required r=Amejia481 a=csadilek

Just a fallback in case add-ons do ever land in our AMO collection with permissions of built-in extensions.

Co-authored-by: default avatarChristian Sadilek <christian.sadilek@gmail.com>
parents 24e645b7 8aeefc77
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ import mozilla.components.feature.addons.update.AddonUpdater
import mozilla.components.feature.addons.update.AddonUpdater.Status
import mozilla.components.support.webextensions.WebExtensionSupport
import mozilla.components.support.webextensions.WebExtensionSupport.installedExtensions
import java.lang.IllegalArgumentException
import java.lang.IllegalStateException
import java.util.Collections.newSetFromMap
import java.util.concurrent.ConcurrentHashMap
@@ -113,6 +114,16 @@ class AddonManager(
        onSuccess: ((Addon) -> Unit) = { },
        onError: ((String, Throwable) -> Unit) = { _, _ -> }
    ) {

        // Verify the add-on doesn't require blocked permissions
        // only available to built-in extensions
        BLOCKED_PERMISSIONS.forEach { blockedPermission ->
            if (addon.permissions.any { it.equals(blockedPermission, ignoreCase = true) }) {
                onError(addon.id, IllegalArgumentException("Addon requires invalid permission $blockedPermission"))
                return
            }
        }

        val pendingAction = addPendingAddonAction()
        engine.installWebExtension(
            id = addon.id,
@@ -268,6 +279,12 @@ class AddonManager(
        action.complete(Unit)
        pendingAddonActions.remove(action)
    }

    companion object {
        // List of invalid permissions for external add-ons i.e. permissions only
        // granted to built-in extensions:
        val BLOCKED_PERMISSIONS = listOf("geckoViewAddons", "nativeMessaging")
    }
}

/**
+26 −0
Original line number Diff line number Diff line
@@ -426,6 +426,32 @@ class AddonManagerTest {
        assertTrue(manager.pendingAddonActions.isEmpty())
    }

    @Test
    fun `installAddon fails for blocked permission`() {
        val addon = Addon(
            id = "ext1",
            permissions = listOf("bookmarks", "geckoviewaddons", "nativemessaging")
        )

        val engine: Engine = mock()

        var throwable: Throwable? = null
        var msg: String? = null
        val manager = AddonManager(mock(), engine, mock(), mock())
        manager.installAddon(addon, onError = { errorMsg, caught ->
            throwable = caught
            msg = errorMsg
        })

        verify(engine, never()).installWebExtension(
            any(), any(), anyBoolean(), anyBoolean(), any(), any()
        )

        assertNotNull(throwable!!)
        assertEquals(msg, addon.id)
        assertTrue(manager.pendingAddonActions.isEmpty())
    }

    @Test
    fun `uninstallAddon successfully`() {
        val installedAddon = Addon(