From e108a5c332ea454a9b5d7c6f0ec88989add1a508 Mon Sep 17 00:00:00 2001 From: Tiger Oakes Date: Tue, 13 Aug 2019 15:31:56 -0400 Subject: [PATCH] Closes #778 - Progressive Web Apps! --- app/build.gradle | 1 + app/src/main/AndroidManifest.xml | 8 ++- .../java/org/mozilla/fenix/HomeActivity.kt | 2 + .../mozilla/fenix/IntentReceiverActivity.kt | 27 ++++---- .../fenix/browser/BaseBrowserFragment.kt | 17 +++-- .../mozilla/fenix/components/Components.kt | 4 +- .../org/mozilla/fenix/components/UseCases.kt | 7 +- .../org/mozilla/fenix/components/Utilities.kt | 15 +++-- .../fenix/components/metrics/Metrics.kt | 2 +- .../toolbar/BrowserToolbarController.kt | 8 +++ .../components/toolbar/DefaultToolbarMenu.kt | 24 +++++-- .../fenix/components/toolbar/ToolbarMenu.kt | 1 + .../fenix/customtabs/AuthCustomTabActivity.kt | 15 +++-- ...ivity.kt => ExternalAppBrowserActivity.kt} | 34 ++++++++-- .../customtabs/ExternalAppBrowserFragment.kt | 65 ++++++++++++++++++- app/src/main/res/navigation/nav_graph.xml | 2 + app/src/main/res/values/strings.xml | 2 + buildSrc/src/main/java/Dependencies.kt | 1 + 18 files changed, 187 insertions(+), 48 deletions(-) rename app/src/main/java/org/mozilla/fenix/customtabs/{CustomTabActivity.kt => ExternalAppBrowserActivity.kt} (54%) diff --git a/app/build.gradle b/app/build.gradle index 3528113bbdf9..1de7e752aeb5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -353,6 +353,7 @@ dependencies { implementation Deps.mozilla_feature_media implementation Deps.mozilla_feature_prompts implementation Deps.mozilla_feature_push + implementation Deps.mozilla_feature_pwa implementation Deps.mozilla_feature_qr implementation Deps.mozilla_feature_search implementation Deps.mozilla_feature_session diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 47a22ca78bdc..84f79770468b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -61,7 +61,7 @@ + + + + + + diff --git a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt index 81e4d5569a57..5a8f2dd017b8 100644 --- a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt @@ -233,6 +233,8 @@ open class HomeActivity : AppCompatActivity(), ShareFragment.TabsSharedCallback ) } + open fun getDirections(customTabSessionId: String?) = NavGraphDirections.actionGlobalBrowser(customTabSessionId) + private fun load( searchTermOrURL: String, newTab: Boolean, diff --git a/app/src/main/java/org/mozilla/fenix/IntentReceiverActivity.kt b/app/src/main/java/org/mozilla/fenix/IntentReceiverActivity.kt index 90b1db780808..2086c286c4a7 100644 --- a/app/src/main/java/org/mozilla/fenix/IntentReceiverActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/IntentReceiverActivity.kt @@ -12,18 +12,23 @@ import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.customtabs.AuthCustomTabActivity -import org.mozilla.fenix.customtabs.CustomTabActivity +import org.mozilla.fenix.customtabs.ExternalAppBrowserActivity import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.metrics import org.mozilla.fenix.utils.Settings +/** + * Processes incoming intents and sends them to the corresponding activity. + */ class IntentReceiverActivity : Activity() { // Holds the intent that initially started this activity // so that it can persist through the speech activity. private var previousIntent: Intent? = null - @Suppress("ComplexMethod") + private fun tabIntentProcessor(isPrivate: Boolean) = + if (isPrivate) components.utils.privateIntentProcessor else components.utils.intentProcessor + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -40,17 +45,14 @@ class IntentReceiverActivity : Activity() { // the HomeActivity. val intent = intent?.let { Intent(intent) } ?: Intent() - val intentProcessors = listOf( - components.utils.customTabIntentProcessor, - if (isPrivate) components.utils.privateIntentProcessor else components.utils.intentProcessor - ) + val intentProcessors = components.utils.externalAppIntentProcessors + tabIntentProcessor(isPrivate) if (intent.getBooleanExtra(SPEECH_PROCESSING, false)) { previousIntent = intent displaySpeechRecognizer() } else { intentProcessors.any { it.process(intent) } - setIntentActivity(intent) + setIntentActivity(intent, isPrivate) startActivity(intent) @@ -59,18 +61,21 @@ class IntentReceiverActivity : Activity() { } } - private fun setIntentActivity(intent: Intent) { + /** + * Sets the activity that this [intent] will launch. + */ + private fun setIntentActivity(intent: Intent, isPrivate: Boolean) { val openToBrowser = when { - components.utils.customTabIntentProcessor.matches(intent) -> { + components.utils.externalAppIntentProcessors.any { it.matches(intent) } -> { val activityClass = if (intent.hasExtra(getString(R.string.intent_extra_auth))) { AuthCustomTabActivity::class } else { - CustomTabActivity::class + ExternalAppBrowserActivity::class } intent.setClassName(applicationContext, activityClass.java.name) true } - intent.action == Intent.ACTION_VIEW || intent.action == Intent.ACTION_SEND -> { + tabIntentProcessor(isPrivate).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 diff --git a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt index 366791e0362a..14b7aafa5edc 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt @@ -323,15 +323,7 @@ abstract class BaseBrowserFragment : Fragment(), BackHandler, SessionManager.Obs toolbar.visibility = View.VISIBLE nestedScrollQuickAction.visibility = View.VISIBLE } - view.swipeRefresh.apply { - val (topMargin, bottomMargin) = if (inFullScreen) 0 to 0 else getEngineMargins() - (layoutParams as CoordinatorLayout.LayoutParams).setMargins( - 0, - topMargin, - 0, - bottomMargin - ) - } + updateLayoutMargins(inFullScreen) }, owner = this, view = view @@ -488,6 +480,13 @@ abstract class BaseBrowserFragment : Fragment(), BackHandler, SessionManager.Obs */ protected abstract fun getAppropriateLayoutGravity(): Int + protected fun updateLayoutMargins(inFullScreen: Boolean) { + view?.swipeRefresh?.apply { + val (topMargin, bottomMargin) = if (inFullScreen) 0 to 0 else getEngineMargins() + (layoutParams as CoordinatorLayout.LayoutParams).setMargins(0, topMargin, 0, bottomMargin) + } + } + /** * Updates the site permissions rules based on user settings. */ diff --git a/app/src/main/java/org/mozilla/fenix/components/Components.kt b/app/src/main/java/org/mozilla/fenix/components/Components.kt index 013f522253c7..585f4fc8d28b 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Components.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Components.kt @@ -19,7 +19,9 @@ class Components(private val context: Context) { val services by lazy { Services(backgroundServices.accountManager) } val core by lazy { Core(context) } val search by lazy { Search(context) } - val useCases by lazy { UseCases(context, core.sessionManager, core.engine.settings, search.searchEngineManager) } + val useCases by lazy { + UseCases(context, core.sessionManager, core.engine.settings, search.searchEngineManager, core.client) + } val utils by lazy { Utilities(context, core.sessionManager, useCases.sessionUseCases, useCases.searchUseCases) } val analytics by lazy { Analytics(context) } val publicSuffixList by lazy { PublicSuffixList(context) } 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 2f018465bab2..93897c5f099c 100644 --- a/app/src/main/java/org/mozilla/fenix/components/UseCases.kt +++ b/app/src/main/java/org/mozilla/fenix/components/UseCases.kt @@ -8,7 +8,9 @@ import android.content.Context import mozilla.components.browser.search.SearchEngineManager import mozilla.components.browser.session.SessionManager import mozilla.components.concept.engine.Settings +import mozilla.components.concept.fetch.Client import mozilla.components.feature.app.links.AppLinksUseCases +import mozilla.components.feature.pwa.WebAppUseCases import mozilla.components.feature.search.SearchUseCases import mozilla.components.feature.session.SessionUseCases import mozilla.components.feature.session.SettingsUseCases @@ -24,7 +26,8 @@ class UseCases( private val context: Context, private val sessionManager: SessionManager, private val engineSettings: Settings, - private val searchEngineManager: SearchEngineManager + private val searchEngineManager: SearchEngineManager, + private val httpClient: Client ) { /** * Use cases that provide engine interactions for a given browser session. @@ -47,4 +50,6 @@ class UseCases( val settingsUseCases by lazy { SettingsUseCases(engineSettings, sessionManager) } val appLinksUseCases by lazy { AppLinksUseCases(context.applicationContext) } + + val webAppUseCases by lazy { WebAppUseCases(context, sessionManager, httpClient) } } diff --git a/app/src/main/java/org/mozilla/fenix/components/Utilities.kt b/app/src/main/java/org/mozilla/fenix/components/Utilities.kt index 4f28afbeba91..8a54f294b226 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Utilities.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Utilities.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.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 @@ -23,18 +25,23 @@ class Utilities( private val searchUseCases: SearchUseCases ) { /** - * Provides intent processing functionality for CustomTab, ACTION_VIEW - * and ACTION_SEND intents. + * Provides intent processing functionality for ACTION_VIEW and ACTION_SEND intents. */ val intentProcessor by lazy { TabIntentProcessor(sessionManager, sessionUseCases.loadUrl, searchUseCases.newTabSearch, isPrivate = false) } + /** + * Provides intent processing functionality for ACTION_VIEW and ACTION_SEND intents in private tabs. + */ val privateIntentProcessor by lazy { TabIntentProcessor(sessionManager, sessionUseCases.loadUrl, searchUseCases.newTabSearch, isPrivate = true) } - val customTabIntentProcessor by lazy { - CustomTabIntentProcessor(sessionManager, sessionUseCases.loadUrl, context.resources) + 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/metrics/Metrics.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/Metrics.kt index baa522b344b4..af3ae4009ac5 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/Metrics.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/Metrics.kt @@ -249,7 +249,7 @@ sealed class Event { enum class Item { SETTINGS, LIBRARY, HELP, DESKTOP_VIEW_ON, DESKTOP_VIEW_OFF, FIND_IN_PAGE, NEW_TAB, NEW_PRIVATE_TAB, SHARE, REPORT_SITE_ISSUE, BACK, FORWARD, RELOAD, STOP, OPEN_IN_FENIX, - SAVE_TO_COLLECTION + SAVE_TO_COLLECTION, ADD_TO_HOMESCREEN } override val extras: Map? diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt index 086fc40bb4de..d83e3d3dcd97 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt @@ -11,7 +11,9 @@ import androidx.core.widget.NestedScrollView import androidx.navigation.NavController import com.google.android.material.bottomsheet.BottomSheetBehavior import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.MainScope import kotlinx.coroutines.ObsoleteCoroutinesApi +import kotlinx.coroutines.launch import mozilla.components.browser.session.Session import mozilla.components.concept.engine.EngineView import org.mozilla.fenix.browser.browsingmode.BrowsingMode @@ -86,6 +88,11 @@ class DefaultBrowserToolbarController( item.isChecked, currentSession ) + ToolbarMenu.Item.AddToHomescreen -> { + MainScope().launch { + context.components.useCases.webAppUseCases.addToHomescreen() + } + } ToolbarMenu.Item.Share -> { val currentUrl = currentSession?.url currentUrl?.apply { @@ -175,6 +182,7 @@ class DefaultBrowserToolbarController( ToolbarMenu.Item.OpenInFenix -> Event.BrowserMenuItemTapped.Item.OPEN_IN_FENIX ToolbarMenu.Item.Share -> Event.BrowserMenuItemTapped.Item.SHARE ToolbarMenu.Item.SaveToCollection -> Event.BrowserMenuItemTapped.Item.SAVE_TO_COLLECTION + ToolbarMenu.Item.AddToHomescreen -> Event.BrowserMenuItemTapped.Item.ADD_TO_HOMESCREEN } context.components.analytics.metrics.track(Event.BrowserMenuItemTapped(eventItem)) 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 e4eccba7c972..6d891da46c22 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 @@ -12,6 +12,7 @@ import mozilla.components.browser.menu.item.BrowserMenuImageText import mozilla.components.browser.menu.item.BrowserMenuItemToolbar import mozilla.components.browser.menu.item.BrowserMenuSwitch import org.mozilla.fenix.browser.browsingmode.BrowsingMode +import mozilla.components.browser.menu.item.SimpleBrowserMenuItem import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.theme.ThemeManager @@ -133,10 +134,20 @@ class DefaultToolbarMenu( onItemTapped.invoke(ToolbarMenu.Item.Library) }, - BrowserMenuSwitch(context.getString(R.string.browser_menu_desktop_site), - requestDesktopStateProvider, { checked -> - onItemTapped.invoke(ToolbarMenu.Item.RequestDesktop(checked)) - }), + BrowserMenuSwitch( + context.getString(R.string.browser_menu_desktop_site), + requestDesktopStateProvider + ) { checked -> + onItemTapped.invoke(ToolbarMenu.Item.RequestDesktop(checked)) + }, + + SimpleBrowserMenuItem( + context.getString(R.string.browser_menu_add_to_homescreen) + ) { + onItemTapped.invoke(ToolbarMenu.Item.AddToHomescreen) + }.apply { + visible = ::shouldShowAddToHomescreen + }, BrowserMenuImageText( context.getString(R.string.browser_menu_find_in_page), @@ -201,4 +212,9 @@ class DefaultToolbarMenu( items } + + private fun shouldShowAddToHomescreen(): Boolean { + return context.components.useCases.webAppUseCases.isPinningSupported() && + context.components.core.sessionManager.selectedSession != null + } } diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt index 4db34ea05921..8a002635ee3b 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt @@ -24,6 +24,7 @@ interface ToolbarMenu { object ReportIssue : Item() object OpenInFenix : Item() object SaveToCollection : Item() + object AddToHomescreen : Item() } val menuBuilder: BrowserMenuBuilder diff --git a/app/src/main/java/org/mozilla/fenix/customtabs/AuthCustomTabActivity.kt b/app/src/main/java/org/mozilla/fenix/customtabs/AuthCustomTabActivity.kt index af762dcc7815..3f5be9900120 100644 --- a/app/src/main/java/org/mozilla/fenix/customtabs/AuthCustomTabActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/customtabs/AuthCustomTabActivity.kt @@ -6,22 +6,25 @@ package org.mozilla.fenix.customtabs import mozilla.components.concept.sync.AccountObserver import mozilla.components.concept.sync.OAuthAccount -import mozilla.components.service.fxa.manager.FxaAccountManager import org.mozilla.fenix.ext.components -class AuthCustomTabActivity : CustomTabActivity() { - private lateinit var accountManager: FxaAccountManager +/** + * A special custom tab for signing into a Firefox Account. The activity is closed once the user is signed in. + */ +class AuthCustomTabActivity : ExternalAppBrowserActivity() { - // Navigate away from this activity when we have successful authentication private val accountStateObserver = object : AccountObserver { + /** + * Navigate away from this activity when we have successful authentication + */ override fun onAuthenticated(account: OAuthAccount, newAccount: Boolean) { - this@AuthCustomTabActivity.finish() + finish() } } override fun onResume() { super.onResume() - accountManager = this.components.backgroundServices.accountManager + val accountManager = this.components.backgroundServices.accountManager accountManager.register(accountStateObserver, this, true) } } diff --git a/app/src/main/java/org/mozilla/fenix/customtabs/CustomTabActivity.kt b/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserActivity.kt similarity index 54% rename from app/src/main/java/org/mozilla/fenix/customtabs/CustomTabActivity.kt rename to app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserActivity.kt index 05ff3ea9a0ff..1c25e9a69b91 100644 --- a/app/src/main/java/org/mozilla/fenix/customtabs/CustomTabActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserActivity.kt @@ -5,7 +5,11 @@ package org.mozilla.fenix.customtabs import androidx.navigation.NavDestination +import androidx.navigation.NavDirections import mozilla.components.browser.session.intent.getSessionId +import mozilla.components.concept.engine.manifest.WebAppManifestParser +import mozilla.components.feature.pwa.ext.getTrustedScope +import mozilla.components.feature.pwa.ext.getWebAppManifest import mozilla.components.support.utils.SafeIntent import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.HomeActivity @@ -15,7 +19,12 @@ import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.theme.CustomTabThemeManager import java.security.InvalidParameterException -open class CustomTabActivity : HomeActivity() { +/** + * Activity that holds the [BrowserFragment] that is launched within an external app, + * such as custom tabs and progressive web apps. + */ +open class ExternalAppBrowserActivity : HomeActivity() { + final override fun getSentryBreadcrumbMessage(destination: NavDestination): String { val fragmentName = resources.getResourceEntryName(destination.id) return "Changing to fragment $fragmentName, isCustomTab: true" @@ -28,12 +37,23 @@ open class CustomTabActivity : 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() + val manifestJson = manifest?.let { WebAppManifestParser().serialize(it).toString() } + val trustedScopes = listOfNotNull( + manifest?.getTrustedScope()?.toString() + ).toTypedArray() + return when (from) { + BrowserDirection.FromGlobal -> + NavGraphDirections.actionGlobalExternalAppBrowser( + activeSessionId = customTabSessionId, + webAppManifest = manifestJson, + trustedScopes = trustedScopes + ) + else -> throw InvalidParameterException( + "Tried to navigate to ExternalAppBrowserFragment from $from" + ) + } } final override fun createBrowsingModeManager() = 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 b20c42139d5c..23ee858c9b17 100644 --- a/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt @@ -6,11 +6,19 @@ package org.mozilla.fenix.customtabs import android.view.Gravity import android.view.View +import androidx.core.net.toUri +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.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 @@ -29,7 +37,10 @@ import org.mozilla.fenix.ext.requireComponents @ExperimentalCoroutinesApi class ExternalAppBrowserFragment : BaseBrowserFragment(), BackHandler { + private val args by navArgs() + private val customTabsIntegration = ViewBoundFeatureWrapper() + private val hideToolbarFeature = ViewBoundFeatureWrapper() override fun initializeUI(view: View): Session? { return super.initializeUI(view)?.also { @@ -41,18 +52,61 @@ class ExternalAppBrowserFragment : BaseBrowserFragment(), BackHandler { requireComponents.core.sessionManager, toolbar, customTabSessionId, - activity, + activity!!, view.nestedScrollQuickAction, view.swipeRefresh, onItemTapped = { browserInteractor.onBrowserToolbarMenuItemTapped(it) } ), owner = this, view = view) + + val trustedScopes = args.trustedScopes.toList().map { it.toUri() } + hideToolbarFeature.set( + feature = WebAppHideToolbarFeature( + requireComponents.core.sessionManager, + toolbar, + customTabSessionId, + trustedScopes + ), + owner = this, + view = toolbar) + // Hot-fix until there's a hideToolbarFeature.onHideStateChanged + if (trustedScopes.isNotEmpty()) { + getSessionById()?.register(object : Session.Observer { + override fun onUrlChanged(session: Session, url: String) { + updateLayoutMargins(false) + } + }) + } + + val manifest = args.webAppManifest?.let { json -> + WebAppManifestParser().parse(json).getOrNull() + } + if (manifest != null) { + activity?.lifecycle?.addObserver( + WebAppActivityFeature( + activity!!, + requireComponents.core.icons, + manifest + ) + ) + activity?.lifecycle?.addObserver( + WebAppSiteControlsFeature( + context?.applicationContext!!, + requireComponents.core.sessionManager, + requireComponents.useCases.sessionUseCases.reload, + customTabSessionId, + manifest + ) + ) + } } consumeFrom(browserStore) { browserToolbarView.update(it) } + + updateLayoutMargins(false) } } @@ -79,8 +133,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 bfd262cdd748..bf4e5a0047a8 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -201,6 +201,8 @@ + + Your Library Desktop site + + Add to homescreen Find in page diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index 1b66d73ca0af..c7952636f901 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -122,6 +122,7 @@ object Deps { const val mozilla_feature_storage = "org.mozilla.components:feature-storage:${Versions.mozilla_android_components}" const val mozilla_feature_prompts = "org.mozilla.components:feature-prompts:${Versions.mozilla_android_components}" const val mozilla_feature_push = "org.mozilla.components:feature-push:${Versions.mozilla_android_components}" + const val mozilla_feature_pwa = "org.mozilla.components:feature-pwa:${Versions.mozilla_android_components}" const val mozilla_feature_toolbar = "org.mozilla.components:feature-toolbar:${Versions.mozilla_android_components}" const val mozilla_feature_findinpage = "org.mozilla.components:feature-findinpage:${Versions.mozilla_android_components}" const val mozilla_feature_site_permissions = "org.mozilla.components:feature-sitepermissions:${Versions.mozilla_android_components}"