Loading components/browser/state/src/main/java/mozilla/components/browser/state/state/CustomTabConfig.kt +21 −1 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import java.util.UUID * @property navigationBarColor Background color for the navigation bar. * @property titleVisible Whether the title should be shown in the custom tab. * @property sessionToken The token associated with the custom tab. * @property externalAppType How this custom tab is being displayed. */ data class CustomTabConfig( val id: String = UUID.randomUUID().toString(), Loading @@ -40,7 +41,8 @@ data class CustomTabConfig( val exitAnimations: Bundle? = null, @ColorInt val navigationBarColor: Int? = null, val titleVisible: Boolean = false, val sessionToken: CustomTabsSessionToken? = null val sessionToken: CustomTabsSessionToken? = null, val externalAppType: ExternalAppType = ExternalAppType.CUSTOM_TAB ) { companion object { Loading @@ -49,6 +51,24 @@ data class CustomTabConfig( } } /** * Represents different contexts that a custom tab session can be displayed in. */ enum class ExternalAppType { /** * Custom tab is displayed as a normal custom tab with toolbar. */ CUSTOM_TAB, /** * Custom tab toolbar is hidden inside a Progressive Web App created by the browser. */ PROGRESSIVE_WEB_APP, /** * Custom tab is displayed fullscreen inside a Trusted Web Activity from an external app. */ TRUSTED_WEB_ACTIVITY } data class CustomTabActionButtonConfig( val description: String, val icon: Bitmap, Loading components/feature/customtabs/src/main/java/mozilla/components/feature/customtabs/CustomTabConfigHelper.kt +3 −1 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import mozilla.components.browser.state.state.CustomTabActionButtonConfig import mozilla.components.browser.state.state.CustomTabConfig import mozilla.components.browser.state.state.CustomTabConfig.Companion.EXTRA_NAVIGATION_BAR_COLOR import mozilla.components.browser.state.state.CustomTabMenuItem import mozilla.components.browser.state.state.ExternalAppType import mozilla.components.support.utils.SafeIntent import mozilla.components.support.utils.toSafeBundle import mozilla.components.support.utils.toSafeIntent Loading Loading @@ -101,7 +102,8 @@ fun createCustomTabConfigFromIntent( CustomTabsSessionToken.getSessionTokenFromIntent(intent) } else { null } }, externalAppType = ExternalAppType.CUSTOM_TAB ) } Loading components/feature/pwa/src/main/java/mozilla/components/feature/pwa/ext/WebAppManifest.kt +3 −1 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ import android.os.Build import android.os.Build.VERSION.SDK_INT import androidx.core.net.toUri import mozilla.components.browser.state.state.CustomTabConfig import mozilla.components.browser.state.state.ExternalAppType import mozilla.components.concept.engine.manifest.WebAppManifest import mozilla.components.support.utils.ColorUtils.isDark Loading Loading @@ -42,7 +43,8 @@ fun WebAppManifest.toCustomTabConfig(): CustomTabConfig { actionButtonConfig = null, showCloseButton = false, showShareMenuItem = true, menuItems = emptyList() menuItems = emptyList(), externalAppType = ExternalAppType.PROGRESSIVE_WEB_APP ) } Loading components/feature/pwa/src/main/java/mozilla/components/feature/pwa/intent/TrustedWebActivityIntentProcessor.kt +2 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ import kotlinx.coroutines.launch import mozilla.components.browser.session.Session import mozilla.components.browser.session.SessionManager import mozilla.components.browser.state.state.CustomTabConfig.Companion.EXTRA_ADDITIONAL_TRUSTED_ORIGINS import mozilla.components.browser.state.state.ExternalAppType import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.fetch.Client import mozilla.components.feature.customtabs.createCustomTabConfigFromIntent Loading Loading @@ -58,7 +59,7 @@ class TrustedWebActivityIntentProcessor( return if (!url.isNullOrEmpty() && matches(intent)) { val session = Session(url, private = false, source = Session.Source.HOME_SCREEN) val customTabConfig = createCustomTabConfigFromIntent(intent, null) session.customTabConfig = customTabConfig session.customTabConfig = customTabConfig.copy(externalAppType = ExternalAppType.TRUSTED_WEB_ACTIVITY) sessionManager.add(session) loadUrlUseCase(url, session, EngineSession.LoadUrlFlags.external()) Loading components/feature/pwa/src/test/java/mozilla/components/feature/pwa/intent/TrustedWebActivityIntentProcessorTest.kt +20 −4 Original line number Diff line number Diff line Loading @@ -13,6 +13,9 @@ import androidx.core.net.toUri import androidx.test.ext.junit.runners.AndroidJUnit4 import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runBlockingTest import mozilla.components.browser.session.SessionManager import mozilla.components.browser.state.state.ExternalAppType import mozilla.components.browser.state.store.BrowserStore import mozilla.components.concept.engine.EngineSession import mozilla.components.feature.customtabs.store.CustomTabsServiceStore import mozilla.components.feature.pwa.intent.WebAppIntentProcessor.Companion.ACTION_VIEW_PWA Loading @@ -20,12 +23,14 @@ import mozilla.components.feature.session.SessionUseCases import mozilla.components.support.test.any import mozilla.components.support.test.eq import mozilla.components.support.test.mock import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertNotNull import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.never import org.mockito.Mockito.spy import org.mockito.Mockito.verify @RunWith(AndroidJUnit4::class) Loading @@ -33,6 +38,14 @@ import org.mockito.Mockito.verify class TrustedWebActivityIntentProcessorTest { private val apiKey = "XXXXXXXXX" private lateinit var store: BrowserStore private lateinit var sessionManager: SessionManager @Before fun setup() { store = BrowserStore() sessionManager = SessionManager(mock(), store) } @Test fun `matches checks if intent is a trusted web activity intent`() { Loading Loading @@ -94,13 +107,16 @@ class TrustedWebActivityIntentProcessorTest { } val loadUrlUseCase: SessionUseCases.DefaultLoadUrlUseCase = mock() val store: CustomTabsServiceStore = mock() val customTabsStore: CustomTabsServiceStore = mock() val processor = spy(TrustedWebActivityIntentProcessor(mock(), loadUrlUseCase, mock(), mock(), apiKey, store)) val processor = TrustedWebActivityIntentProcessor(sessionManager, loadUrlUseCase, mock(), mock(), apiKey, customTabsStore) assertTrue(processor.process(intent)) val sessionState = store.state.customTabs.first() assertNotNull(sessionState.config) assertEquals(ExternalAppType.TRUSTED_WEB_ACTIVITY, sessionState.config.externalAppType) verify(loadUrlUseCase).invoke(eq("https://example.com"), any(), eq(EngineSession.LoadUrlFlags.external())) verify(store, never()).state verify(customTabsStore, never()).state } } Loading
components/browser/state/src/main/java/mozilla/components/browser/state/state/CustomTabConfig.kt +21 −1 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import java.util.UUID * @property navigationBarColor Background color for the navigation bar. * @property titleVisible Whether the title should be shown in the custom tab. * @property sessionToken The token associated with the custom tab. * @property externalAppType How this custom tab is being displayed. */ data class CustomTabConfig( val id: String = UUID.randomUUID().toString(), Loading @@ -40,7 +41,8 @@ data class CustomTabConfig( val exitAnimations: Bundle? = null, @ColorInt val navigationBarColor: Int? = null, val titleVisible: Boolean = false, val sessionToken: CustomTabsSessionToken? = null val sessionToken: CustomTabsSessionToken? = null, val externalAppType: ExternalAppType = ExternalAppType.CUSTOM_TAB ) { companion object { Loading @@ -49,6 +51,24 @@ data class CustomTabConfig( } } /** * Represents different contexts that a custom tab session can be displayed in. */ enum class ExternalAppType { /** * Custom tab is displayed as a normal custom tab with toolbar. */ CUSTOM_TAB, /** * Custom tab toolbar is hidden inside a Progressive Web App created by the browser. */ PROGRESSIVE_WEB_APP, /** * Custom tab is displayed fullscreen inside a Trusted Web Activity from an external app. */ TRUSTED_WEB_ACTIVITY } data class CustomTabActionButtonConfig( val description: String, val icon: Bitmap, Loading
components/feature/customtabs/src/main/java/mozilla/components/feature/customtabs/CustomTabConfigHelper.kt +3 −1 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import mozilla.components.browser.state.state.CustomTabActionButtonConfig import mozilla.components.browser.state.state.CustomTabConfig import mozilla.components.browser.state.state.CustomTabConfig.Companion.EXTRA_NAVIGATION_BAR_COLOR import mozilla.components.browser.state.state.CustomTabMenuItem import mozilla.components.browser.state.state.ExternalAppType import mozilla.components.support.utils.SafeIntent import mozilla.components.support.utils.toSafeBundle import mozilla.components.support.utils.toSafeIntent Loading Loading @@ -101,7 +102,8 @@ fun createCustomTabConfigFromIntent( CustomTabsSessionToken.getSessionTokenFromIntent(intent) } else { null } }, externalAppType = ExternalAppType.CUSTOM_TAB ) } Loading
components/feature/pwa/src/main/java/mozilla/components/feature/pwa/ext/WebAppManifest.kt +3 −1 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ import android.os.Build import android.os.Build.VERSION.SDK_INT import androidx.core.net.toUri import mozilla.components.browser.state.state.CustomTabConfig import mozilla.components.browser.state.state.ExternalAppType import mozilla.components.concept.engine.manifest.WebAppManifest import mozilla.components.support.utils.ColorUtils.isDark Loading Loading @@ -42,7 +43,8 @@ fun WebAppManifest.toCustomTabConfig(): CustomTabConfig { actionButtonConfig = null, showCloseButton = false, showShareMenuItem = true, menuItems = emptyList() menuItems = emptyList(), externalAppType = ExternalAppType.PROGRESSIVE_WEB_APP ) } Loading
components/feature/pwa/src/main/java/mozilla/components/feature/pwa/intent/TrustedWebActivityIntentProcessor.kt +2 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ import kotlinx.coroutines.launch import mozilla.components.browser.session.Session import mozilla.components.browser.session.SessionManager import mozilla.components.browser.state.state.CustomTabConfig.Companion.EXTRA_ADDITIONAL_TRUSTED_ORIGINS import mozilla.components.browser.state.state.ExternalAppType import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.fetch.Client import mozilla.components.feature.customtabs.createCustomTabConfigFromIntent Loading Loading @@ -58,7 +59,7 @@ class TrustedWebActivityIntentProcessor( return if (!url.isNullOrEmpty() && matches(intent)) { val session = Session(url, private = false, source = Session.Source.HOME_SCREEN) val customTabConfig = createCustomTabConfigFromIntent(intent, null) session.customTabConfig = customTabConfig session.customTabConfig = customTabConfig.copy(externalAppType = ExternalAppType.TRUSTED_WEB_ACTIVITY) sessionManager.add(session) loadUrlUseCase(url, session, EngineSession.LoadUrlFlags.external()) Loading
components/feature/pwa/src/test/java/mozilla/components/feature/pwa/intent/TrustedWebActivityIntentProcessorTest.kt +20 −4 Original line number Diff line number Diff line Loading @@ -13,6 +13,9 @@ import androidx.core.net.toUri import androidx.test.ext.junit.runners.AndroidJUnit4 import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runBlockingTest import mozilla.components.browser.session.SessionManager import mozilla.components.browser.state.state.ExternalAppType import mozilla.components.browser.state.store.BrowserStore import mozilla.components.concept.engine.EngineSession import mozilla.components.feature.customtabs.store.CustomTabsServiceStore import mozilla.components.feature.pwa.intent.WebAppIntentProcessor.Companion.ACTION_VIEW_PWA Loading @@ -20,12 +23,14 @@ import mozilla.components.feature.session.SessionUseCases import mozilla.components.support.test.any import mozilla.components.support.test.eq import mozilla.components.support.test.mock import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertNotNull import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.never import org.mockito.Mockito.spy import org.mockito.Mockito.verify @RunWith(AndroidJUnit4::class) Loading @@ -33,6 +38,14 @@ import org.mockito.Mockito.verify class TrustedWebActivityIntentProcessorTest { private val apiKey = "XXXXXXXXX" private lateinit var store: BrowserStore private lateinit var sessionManager: SessionManager @Before fun setup() { store = BrowserStore() sessionManager = SessionManager(mock(), store) } @Test fun `matches checks if intent is a trusted web activity intent`() { Loading Loading @@ -94,13 +107,16 @@ class TrustedWebActivityIntentProcessorTest { } val loadUrlUseCase: SessionUseCases.DefaultLoadUrlUseCase = mock() val store: CustomTabsServiceStore = mock() val customTabsStore: CustomTabsServiceStore = mock() val processor = spy(TrustedWebActivityIntentProcessor(mock(), loadUrlUseCase, mock(), mock(), apiKey, store)) val processor = TrustedWebActivityIntentProcessor(sessionManager, loadUrlUseCase, mock(), mock(), apiKey, customTabsStore) assertTrue(processor.process(intent)) val sessionState = store.state.customTabs.first() assertNotNull(sessionState.config) assertEquals(ExternalAppType.TRUSTED_WEB_ACTIVITY, sessionState.config.externalAppType) verify(loadUrlUseCase).invoke(eq("https://example.com"), any(), eq(EngineSession.LoadUrlFlags.external())) verify(store, never()).state verify(customTabsStore, never()).state } }