From 78bc8297353a97a2095272b73c5436155da01441 Mon Sep 17 00:00:00 2001 From: Tiger Oakes Date: Tue, 8 Oct 2019 16:50:16 -0700 Subject: [PATCH] Closes #778 - Progressive Web Apps! (#4914) --- app/src/main/AndroidManifest.xml | 6 +++ .../java/org/mozilla/fenix/FeatureFlags.kt | 12 +++++ .../fenix/components/FindInPageIntegration.kt | 6 +-- .../fenix/components/IntentProcessors.kt | 3 ++ .../org/mozilla/fenix/components/UseCases.kt | 5 ++- .../components/toolbar/DefaultToolbarMenu.kt | 2 +- .../customtabs/ExternalAppBrowserActivity.kt | 24 +++++++--- .../customtabs/ExternalAppBrowserFragment.kt | 44 +++++++++++++++++-- app/src/main/res/navigation/nav_graph.xml | 6 +-- 9 files changed, 90 insertions(+), 18 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fdeccbe52..b3771542f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -113,6 +113,12 @@ + + + + + + diff --git a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt index ac291565e..497e6c560 100644 --- a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt +++ b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt @@ -49,4 +49,16 @@ object FeatureFlags { * Gives option in Settings to disable auto play media */ val autoPlayMedia = nightly or debug + + val granularDataDeletion = nightly or debug + + /** + * Gives option in Settings to Delete Browsing Data on new menu option Quit + */ + val deleteDataOnQuit = nightly or debug + + /** + * Allows Progressive Web Apps to be installed to the device home screen. + */ + val progressiveWebApps = nightly or debug } diff --git a/app/src/main/java/org/mozilla/fenix/components/FindInPageIntegration.kt b/app/src/main/java/org/mozilla/fenix/components/FindInPageIntegration.kt index 754510840..859ab2bc9 100644 --- a/app/src/main/java/org/mozilla/fenix/components/FindInPageIntegration.kt +++ b/app/src/main/java/org/mozilla/fenix/components/FindInPageIntegration.kt @@ -32,12 +32,12 @@ class FindInPageIntegration( } override fun onLaunch(view: View, feature: LifecycleAwareFeature) { - store.state.findCustomTabOrSelectedTab(sessionId)?.let { session -> - if (session !is CustomTabSessionState) { + store.state.findCustomTabOrSelectedTab(sessionId)?.let { tab -> + if (tab is CustomTabSessionState) { toolbar.visibility = View.GONE } view.visibility = View.VISIBLE - (feature as FindInPageFeature).bind(session) + (feature as FindInPageFeature).bind(tab) view.layoutParams.height = toolbar.height } } diff --git a/app/src/main/java/org/mozilla/fenix/components/IntentProcessors.kt b/app/src/main/java/org/mozilla/fenix/components/IntentProcessors.kt index 514d74dc4..59e7c14c9 100644 --- a/app/src/main/java/org/mozilla/fenix/components/IntentProcessors.kt +++ b/app/src/main/java/org/mozilla/fenix/components/IntentProcessors.kt @@ -8,6 +8,8 @@ import android.content.Context import mozilla.components.browser.session.SessionManager import mozilla.components.feature.customtabs.CustomTabIntentProcessor import mozilla.components.feature.intent.processing.TabIntentProcessor +import mozilla.components.feature.pwa.ManifestStorage +import mozilla.components.feature.pwa.intent.WebAppIntentProcessor import mozilla.components.feature.search.SearchUseCases import mozilla.components.feature.session.SessionUseCases import org.mozilla.fenix.test.Mockable @@ -38,6 +40,7 @@ class IntentProcessors( val externalAppIntentProcessors by lazy { listOf( + WebAppIntentProcessor(sessionManager, sessionUseCases.loadUrl, ManifestStorage(context)), CustomTabIntentProcessor(sessionManager, sessionUseCases.loadUrl, context.resources) ) } diff --git a/app/src/main/java/org/mozilla/fenix/components/UseCases.kt b/app/src/main/java/org/mozilla/fenix/components/UseCases.kt index cd902f64b..fc3de1673 100644 --- a/app/src/main/java/org/mozilla/fenix/components/UseCases.kt +++ b/app/src/main/java/org/mozilla/fenix/components/UseCases.kt @@ -18,6 +18,7 @@ import mozilla.components.feature.search.SearchUseCases import mozilla.components.feature.session.SessionUseCases import mozilla.components.feature.session.SettingsUseCases import mozilla.components.feature.tabs.TabsUseCases +import org.mozilla.fenix.FeatureFlags.progressiveWebApps import org.mozilla.fenix.test.Mockable /** @@ -55,7 +56,9 @@ class UseCases( val appLinksUseCases by lazy { AppLinksUseCases(context.applicationContext) } - val webAppUseCases by lazy { WebAppUseCases(context, sessionManager, httpClient, supportWebApps = false) } + val webAppUseCases by lazy { + WebAppUseCases(context, sessionManager, httpClient, supportWebApps = progressiveWebApps) + } val downloadUseCases by lazy { DownloadsUseCases(store) } diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt index 2de009816..3a8664061 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt @@ -11,9 +11,9 @@ import mozilla.components.browser.menu.item.BrowserMenuHighlightableItem import mozilla.components.browser.menu.item.BrowserMenuImageText import mozilla.components.browser.menu.item.BrowserMenuItemToolbar import mozilla.components.browser.menu.item.BrowserMenuImageSwitch +import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R -import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.ext.asActivity import org.mozilla.fenix.ext.components import org.mozilla.fenix.theme.ThemeManager diff --git a/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserActivity.kt b/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserActivity.kt index a1b08e668..9d8ac1be3 100644 --- a/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserActivity.kt @@ -5,8 +5,11 @@ package org.mozilla.fenix.customtabs import androidx.navigation.NavDestination +import androidx.navigation.NavDirections import mozilla.components.browser.session.runWithSession +import mozilla.components.concept.engine.manifest.WebAppManifestParser import mozilla.components.feature.intent.ext.getSessionId +import mozilla.components.feature.pwa.ext.getWebAppManifest import mozilla.components.support.utils.SafeIntent import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.HomeActivity @@ -23,6 +26,7 @@ import java.security.InvalidParameterException * such as custom tabs and progressive web apps. */ open class ExternalAppBrowserActivity : HomeActivity() { + final override fun getBreadcrumbMessage(destination: NavDestination): String { val fragmentName = resources.getResourceEntryName(destination.id) return "Changing to fragment $fragmentName, isCustomTab: true" @@ -35,12 +39,20 @@ open class ExternalAppBrowserActivity : HomeActivity() { override fun getNavDirections( from: BrowserDirection, customTabSessionId: String? - ) = when (from) { - BrowserDirection.FromGlobal -> - NavGraphDirections.actionGlobalExternalAppBrowser(customTabSessionId) - else -> throw InvalidParameterException( - "Tried to navigate to ExternalAppBrowserFragment from $from" - ) + ): NavDirections { + val manifest = intent + .getWebAppManifest() + ?.let { WebAppManifestParser().serialize(it).toString() } + return when (from) { + BrowserDirection.FromGlobal -> + NavGraphDirections.actionGlobalExternalAppBrowser( + activeSessionId = customTabSessionId, + webAppManifest = manifest + ) + else -> throw InvalidParameterException( + "Tried to navigate to ExternalAppBrowserFragment from $from" + ) + } } final override fun createBrowsingModeManager(initialMode: BrowsingMode) = diff --git a/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt index 389c4e477..959a12678 100644 --- a/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt @@ -6,13 +6,20 @@ package org.mozilla.fenix.customtabs import android.view.Gravity import android.view.View +import androidx.core.view.isGone +import androidx.navigation.fragment.navArgs import kotlinx.android.synthetic.main.component_search.* import kotlinx.android.synthetic.main.fragment_browser.view.* import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ObsoleteCoroutinesApi import mozilla.components.browser.session.Session +import mozilla.components.concept.engine.manifest.WebAppManifestParser +import mozilla.components.concept.engine.manifest.getOrNull +import mozilla.components.feature.pwa.ext.getTrustedScope import mozilla.components.feature.pwa.ext.trustedOrigins +import mozilla.components.feature.pwa.feature.WebAppActivityFeature import mozilla.components.feature.pwa.feature.WebAppHideToolbarFeature +import mozilla.components.feature.pwa.feature.WebAppSiteControlsFeature import mozilla.components.feature.sitepermissions.SitePermissions import mozilla.components.lib.state.ext.consumeFrom import mozilla.components.support.base.feature.BackHandler @@ -32,6 +39,8 @@ import org.mozilla.fenix.ext.requireComponents @ExperimentalCoroutinesApi class ExternalAppBrowserFragment : BaseBrowserFragment(), BackHandler { + private val args by navArgs() + private val customTabsIntegration = ViewBoundFeatureWrapper() private val hideToolbarFeature = ViewBoundFeatureWrapper() @@ -40,6 +49,11 @@ class ExternalAppBrowserFragment : BaseBrowserFragment(), BackHandler { val activity = requireActivity() val components = activity.components + val manifest = args.webAppManifest?.let { json -> + WebAppManifestParser().parse(json).getOrNull() + } + val trustedScopes = listOfNotNull(manifest?.getTrustedScope()) + customTabSessionId?.let { customTabSessionId -> customTabsIntegration.set( feature = CustomTabsIntegration( @@ -59,12 +73,31 @@ class ExternalAppBrowserFragment : BaseBrowserFragment(), BackHandler { requireComponents.core.sessionManager, toolbar, customTabSessionId, - emptyList() + trustedScopes ) { toolbarVisible -> updateLayoutMargins(inFullScreen = !toolbarVisible) }, owner = this, view = toolbar) + + if (manifest != null) { + activity.lifecycle.addObserver( + WebAppActivityFeature( + activity, + components.core.icons, + manifest + ) + ) + viewLifecycleOwner.lifecycle.addObserver( + WebAppSiteControlsFeature( + activity.applicationContext, + requireComponents.core.sessionManager, + requireComponents.useCases.sessionUseCases.reload, + customTabSessionId, + manifest + ) + ) + } } consumeFrom(browserStore) { @@ -121,8 +154,13 @@ class ExternalAppBrowserFragment : BaseBrowserFragment(), BackHandler { } override fun getEngineMargins(): Pair { - val toolbarSize = resources.getDimensionPixelSize(R.dimen.browser_toolbar_height) - return toolbarSize to 0 + val toolbarHidden = toolbar.isGone + return if (toolbarHidden) { + 0 to 0 + } else { + val toolbarSize = resources.getDimensionPixelSize(R.dimen.browser_toolbar_height) + toolbarSize to 0 + } } override fun getAppropriateLayoutGravity() = Gravity.TOP diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 2783aca23..925056f4a 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -198,10 +198,8 @@ android:id="@+id/externalAppBrowserFragment" android:name="org.mozilla.fenix.customtabs.ExternalAppBrowserFragment" tools:layout="@layout/fragment_browser"> - + +