Unverified Commit 5f393bd5 authored by Severin Rudie's avatar Severin Rudie Committed by GitHub
Browse files

For #5334: added private custom tab processor (#6845)

* For #5334: added private custom tab processor

* For #5334 - Fixes up IntentReceiverActivity for handling intents

* For 5334: update styling for private custom tabbs

* For 5334: update tests to account for new processors

Note that two are still failing. These appear to be true failures, and will be corrected in a later commit.

* For 5334: fixes bug introduced by changes to IntentReceiverActivity

RCA: intent className and extra were previously set based on which processors matched, not which successfully processed. This patch reintroduces that behavior.

* For 5334: add tests for custom tabs processing
parent 4fb26a06
Loading
Loading
Loading
Loading
+60 −36
Original line number Diff line number Diff line
@@ -10,14 +10,52 @@ import android.os.Bundle
import androidx.annotation.VisibleForTesting
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import mozilla.components.feature.intent.processing.TabIntentProcessor
import mozilla.components.feature.intent.processing.IntentProcessor
import mozilla.components.support.utils.Browsers
import org.mozilla.fenix.components.IntentProcessors
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.customtabs.ExternalAppBrowserActivity
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.shortcut.NewTabShortcutIntentProcessor

enum class IntentProcessorType {
    EXTERNAL_APP, NEW_TAB, OTHER;

    /**
     * The destination activity based on this intent
     */
    val activityClassName: String
        get() = when (this) {
            EXTERNAL_APP -> ExternalAppBrowserActivity::class.java.name
            NEW_TAB -> HomeActivity::class.java.name
            OTHER -> HomeActivity::class.java.name
        }

    /**
     * Should this intent automatically navigate to the browser?
     */
    fun shouldOpenToBrowser(intent: Intent): Boolean = when (this) {
        EXTERNAL_APP -> true
        NEW_TAB -> intent.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY == 0
        OTHER -> false
    }
}

/**
 * Classifies the [IntentType] based on the [IntentProcessor] that handled the [Intent]
 */
fun IntentProcessor?.getType(intentProcessors: IntentProcessors): IntentProcessorType {
    return when {
        intentProcessors.externalAppIntentProcessors.contains(this) ||
            intentProcessors.customTabIntentProcessor == this ||
            intentProcessors.privateCustomTabIntentProcessor == this -> IntentProcessorType.EXTERNAL_APP
        intentProcessors.intentProcessor == this ||
                intentProcessors.privateIntentProcessor == this -> IntentProcessorType.NEW_TAB
        else -> IntentProcessorType.OTHER
    }
}

/**
 * Processes incoming intents and sends them to the corresponding activity.
 */
@@ -47,49 +85,35 @@ class IntentReceiverActivity : Activity() {
            ))
        }

        val tabIntentProcessor = if (settings().openLinksInAPrivateTab) {
        val modeDependentProcessors = if (settings().openLinksInAPrivateTab) {
                components.analytics.metrics.track(Event.OpenedLink(Event.OpenedLink.Mode.PRIVATE))
                listOf(
                    components.intentProcessors.privateCustomTabIntentProcessor,
                    components.intentProcessors.privateIntentProcessor
                )
            } else {
                components.analytics.metrics.track(Event.OpenedLink(Event.OpenedLink.Mode.NORMAL))
                listOf(
                    components.intentProcessors.customTabIntentProcessor,
                    components.intentProcessors.intentProcessor
                )
            }

        val intentProcessors = components.intentProcessors.externalAppIntentProcessors +
                tabIntentProcessor +
                modeDependentProcessors +
                NewTabShortcutIntentProcessor()

        // Call process for side effects, short on the first that returns true
        intentProcessors.any { it.process(intent) }
        setIntentActivity(intent, tabIntentProcessor)

        val intentProcessorType = intentProcessors
            .firstOrNull { it.matches(intent) }
            .getType(components.intentProcessors)

        intent.setClassName(applicationContext, intentProcessorType.activityClassName)
        intent.putExtra(HomeActivity.OPEN_TO_BROWSER, intentProcessorType.shouldOpenToBrowser(intent))
        startActivity(intent)

        finish()
    }

    /**
     * Sets the activity that this [intent] will launch.
     */
    private fun setIntentActivity(intent: Intent, tabIntentProcessor: TabIntentProcessor) {
        val openToBrowser = when {
            components.intentProcessors.externalAppIntentProcessors.any { it.matches(intent) } -> {
                intent.setClassName(applicationContext, ExternalAppBrowserActivity::class.java.name)
                true
            }
            tabIntentProcessor.matches(intent) -> {
                intent.setClassName(applicationContext, HomeActivity::class.java.name)
                // This Intent was launched from history (recent apps). Android will redeliver the
                // original Intent (which might be a VIEW intent). However if there's no active browsing
                // session then we do not want to re-process the Intent and potentially re-open a website
                // from a session that the user already "erased".
                intent.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY == 0
            }
            else -> {
                intent.setClassName(applicationContext, HomeActivity::class.java.name)
                false
            }
        }

        intent.putExtra(HomeActivity.OPEN_TO_BROWSER, openToBrowser)
    }
}
+0 −6
Original line number Diff line number Diff line
@@ -44,9 +44,3 @@ class DefaultBrowsingModeManager(
            modeDidChange(value)
        }
}

class CustomTabBrowsingModeManager : BrowsingModeManager {
    override var mode
        get() = BrowsingMode.Normal
        set(_) { /* no-op */ }
}
+6 −3
Original line number Diff line number Diff line
@@ -45,7 +45,11 @@ class IntentProcessors(
    }

    val customTabIntentProcessor by lazy {
        CustomTabIntentProcessor(sessionManager, sessionUseCases.loadUrl, context.resources)
        CustomTabIntentProcessor(sessionManager, sessionUseCases.loadUrl, context.resources, isPrivate = false)
    }

    val privateCustomTabIntentProcessor by lazy {
        CustomTabIntentProcessor(sessionManager, sessionUseCases.loadUrl, context.resources, isPrivate = true)
    }

    val externalAppIntentProcessors by lazy {
@@ -58,8 +62,7 @@ class IntentProcessors(
                apiKey = BuildConfig.DIGITAL_ASSET_LINKS_TOKEN,
                store = customTabsStore
            ),
            WebAppIntentProcessor(sessionManager, sessionUseCases.loadUrl, ManifestStorage(context)),
            customTabIntentProcessor
            WebAppIntentProcessor(sessionManager, sessionUseCases.loadUrl, ManifestStorage(context))
        )
    }
}
+11 −1
Original line number Diff line number Diff line
@@ -27,7 +27,8 @@ class CustomTabsIntegration(
    sessionId: String,
    activity: Activity,
    engineLayout: View,
    onItemTapped: (ToolbarMenu.Item) -> Unit = {}
    onItemTapped: (ToolbarMenu.Item) -> Unit = {},
    isPrivate: Boolean
) : LifecycleAwareFeature, UserInteractionHandler {

    init {
@@ -75,6 +76,15 @@ class CustomTabsIntegration(
                )!!
            )
        }

        // If in private mode, override toolbar background to use private color
        // See #5334
        if (isPrivate) {
            toolbar.background = AppCompatResources.getDrawable(
                activity,
                R.drawable.toolbar_background
            )
        }
    }

    private val customTabToolbarMenu by lazy {
+0 −8
Original line number Diff line number Diff line
@@ -14,11 +14,8 @@ import mozilla.components.support.utils.SafeIntent
import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.NavGraphDirections
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.browser.browsingmode.CustomTabBrowsingModeManager
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.theme.CustomTabThemeManager
import java.security.InvalidParameterException

/**
@@ -60,11 +57,6 @@ open class ExternalAppBrowserActivity : HomeActivity() {
        }
    }

    final override fun createBrowsingModeManager(initialMode: BrowsingMode) =
        CustomTabBrowsingModeManager()

    final override fun createThemeManager() = CustomTabThemeManager()

    override fun onDestroy() {
        super.onDestroy()

Loading