2019-08-12 18:31:59 +02:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
package org.mozilla.fenix.customtabs
|
|
|
|
|
2019-10-25 06:38:15 +02:00
|
|
|
import android.content.Context
|
2019-08-12 18:31:59 +02:00
|
|
|
import android.view.View
|
2019-10-09 01:50:16 +02:00
|
|
|
import androidx.navigation.fragment.navArgs
|
2019-11-26 01:43:32 +01:00
|
|
|
import kotlinx.android.synthetic.main.component_browser_top_toolbar.*
|
2019-08-12 18:31:59 +02:00
|
|
|
import kotlinx.android.synthetic.main.fragment_browser.view.*
|
|
|
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
|
|
import mozilla.components.browser.session.Session
|
2019-10-09 01:50:16 +02:00
|
|
|
import mozilla.components.concept.engine.manifest.WebAppManifestParser
|
|
|
|
import mozilla.components.concept.engine.manifest.getOrNull
|
2019-10-25 06:38:15 +02:00
|
|
|
import mozilla.components.feature.contextmenu.ContextMenuCandidate
|
2019-11-14 21:02:27 +01:00
|
|
|
import mozilla.components.feature.customtabs.CustomTabWindowFeature
|
2019-10-09 01:50:16 +02:00
|
|
|
import mozilla.components.feature.pwa.ext.getTrustedScope
|
2019-09-20 19:28:49 +02:00
|
|
|
import mozilla.components.feature.pwa.ext.trustedOrigins
|
2019-11-07 20:30:03 +01:00
|
|
|
import mozilla.components.feature.pwa.feature.ManifestUpdateFeature
|
2019-10-09 01:50:16 +02:00
|
|
|
import mozilla.components.feature.pwa.feature.WebAppActivityFeature
|
2019-09-20 19:28:49 +02:00
|
|
|
import mozilla.components.feature.pwa.feature.WebAppHideToolbarFeature
|
2019-10-09 01:50:16 +02:00
|
|
|
import mozilla.components.feature.pwa.feature.WebAppSiteControlsFeature
|
2019-10-02 06:45:04 +02:00
|
|
|
import mozilla.components.feature.session.TrackingProtectionUseCases
|
2019-08-12 18:31:59 +02:00
|
|
|
import mozilla.components.feature.sitepermissions.SitePermissions
|
|
|
|
import mozilla.components.lib.state.ext.consumeFrom
|
2019-11-28 00:02:47 +01:00
|
|
|
import mozilla.components.support.base.feature.UserInteractionHandler
|
2019-08-12 18:31:59 +02:00
|
|
|
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
|
2019-11-07 20:30:03 +01:00
|
|
|
import mozilla.components.support.ktx.android.arch.lifecycle.addObservers
|
2019-08-12 18:31:59 +02:00
|
|
|
import org.mozilla.fenix.R
|
|
|
|
import org.mozilla.fenix.browser.BaseBrowserFragment
|
2019-10-25 06:38:15 +02:00
|
|
|
import org.mozilla.fenix.browser.CustomTabContextMenuCandidate
|
|
|
|
import org.mozilla.fenix.browser.FenixSnackbarDelegate
|
2019-09-20 19:28:49 +02:00
|
|
|
import org.mozilla.fenix.ext.components
|
2019-08-12 18:31:59 +02:00
|
|
|
import org.mozilla.fenix.ext.nav
|
|
|
|
import org.mozilla.fenix.ext.requireComponents
|
2019-12-30 13:11:24 +01:00
|
|
|
import org.mozilla.fenix.ext.settings
|
2019-08-12 18:31:59 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Fragment used for browsing the web within external apps.
|
|
|
|
*/
|
|
|
|
@ExperimentalCoroutinesApi
|
2019-11-28 00:02:47 +01:00
|
|
|
class ExternalAppBrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
|
2019-08-12 18:31:59 +02:00
|
|
|
|
2019-10-09 01:50:16 +02:00
|
|
|
private val args by navArgs<ExternalAppBrowserFragmentArgs>()
|
|
|
|
|
2019-08-12 18:31:59 +02:00
|
|
|
private val customTabsIntegration = ViewBoundFeatureWrapper<CustomTabsIntegration>()
|
2019-11-14 21:02:27 +01:00
|
|
|
private val windowFeature = ViewBoundFeatureWrapper<CustomTabWindowFeature>()
|
2019-09-20 19:28:49 +02:00
|
|
|
private val hideToolbarFeature = ViewBoundFeatureWrapper<WebAppHideToolbarFeature>()
|
2019-08-12 18:31:59 +02:00
|
|
|
|
2019-10-25 05:55:24 +02:00
|
|
|
@Suppress("LongMethod")
|
2019-08-12 18:31:59 +02:00
|
|
|
override fun initializeUI(view: View): Session? {
|
|
|
|
return super.initializeUI(view)?.also {
|
2019-09-20 19:28:49 +02:00
|
|
|
val activity = requireActivity()
|
|
|
|
val components = activity.components
|
2019-08-12 18:31:59 +02:00
|
|
|
|
2019-10-09 01:50:16 +02:00
|
|
|
val manifest = args.webAppManifest?.let { json ->
|
|
|
|
WebAppManifestParser().parse(json).getOrNull()
|
|
|
|
}
|
|
|
|
val trustedScopes = listOfNotNull(manifest?.getTrustedScope())
|
|
|
|
|
2019-08-12 18:31:59 +02:00
|
|
|
customTabSessionId?.let { customTabSessionId ->
|
|
|
|
customTabsIntegration.set(
|
|
|
|
feature = CustomTabsIntegration(
|
2019-11-12 02:10:14 +01:00
|
|
|
sessionManager = requireComponents.core.sessionManager,
|
|
|
|
toolbar = toolbar,
|
|
|
|
sessionId = customTabSessionId,
|
|
|
|
activity = activity,
|
|
|
|
engineLayout = view.swipeRefresh,
|
2019-12-06 19:57:54 +01:00
|
|
|
onItemTapped = { browserInteractor.onBrowserToolbarMenuItemTapped(it) },
|
2020-02-10 22:57:29 +01:00
|
|
|
isPrivate = requireComponents.browsingModeManager.mode.isPrivate,
|
2019-12-30 13:11:24 +01:00
|
|
|
shouldReverseItems = !activity.settings().shouldUseBottomToolbar
|
2019-08-12 18:31:59 +02:00
|
|
|
),
|
|
|
|
owner = this,
|
2019-12-12 22:27:16 +01:00
|
|
|
view = view
|
|
|
|
)
|
2019-09-20 19:28:49 +02:00
|
|
|
|
2019-11-14 21:02:27 +01:00
|
|
|
windowFeature.set(
|
|
|
|
feature = CustomTabWindowFeature(
|
|
|
|
activity,
|
|
|
|
components.core.store,
|
|
|
|
customTabSessionId
|
|
|
|
),
|
|
|
|
owner = this,
|
|
|
|
view = view
|
|
|
|
)
|
|
|
|
|
2019-09-20 19:28:49 +02:00
|
|
|
hideToolbarFeature.set(
|
|
|
|
feature = WebAppHideToolbarFeature(
|
|
|
|
requireComponents.core.sessionManager,
|
|
|
|
toolbar,
|
|
|
|
customTabSessionId,
|
2019-10-09 01:50:16 +02:00
|
|
|
trustedScopes
|
2019-09-20 19:28:49 +02:00
|
|
|
) { toolbarVisible ->
|
|
|
|
updateLayoutMargins(inFullScreen = !toolbarVisible)
|
|
|
|
},
|
|
|
|
owner = this,
|
2019-10-25 06:38:15 +02:00
|
|
|
view = toolbar
|
|
|
|
)
|
2019-10-09 01:50:16 +02:00
|
|
|
|
|
|
|
if (manifest != null) {
|
2019-11-07 20:30:03 +01:00
|
|
|
activity.lifecycle.addObservers(
|
2019-10-09 01:50:16 +02:00
|
|
|
WebAppActivityFeature(
|
|
|
|
activity,
|
|
|
|
components.core.icons,
|
|
|
|
manifest
|
2019-11-07 20:30:03 +01:00
|
|
|
),
|
|
|
|
ManifestUpdateFeature(
|
|
|
|
activity.applicationContext,
|
|
|
|
requireComponents.core.sessionManager,
|
2019-11-07 22:30:37 +01:00
|
|
|
requireComponents.core.webAppShortcutManager,
|
2019-11-07 20:30:03 +01:00
|
|
|
requireComponents.core.webAppManifestStorage,
|
|
|
|
customTabSessionId,
|
|
|
|
manifest
|
2019-10-09 01:50:16 +02:00
|
|
|
)
|
|
|
|
)
|
|
|
|
viewLifecycleOwner.lifecycle.addObserver(
|
|
|
|
WebAppSiteControlsFeature(
|
|
|
|
activity.applicationContext,
|
|
|
|
requireComponents.core.sessionManager,
|
|
|
|
requireComponents.useCases.sessionUseCases.reload,
|
|
|
|
customTabSessionId,
|
|
|
|
manifest
|
|
|
|
)
|
|
|
|
)
|
2019-10-25 05:55:24 +02:00
|
|
|
} else {
|
|
|
|
viewLifecycleOwner.lifecycle.addObserver(
|
|
|
|
PoweredByNotification(
|
|
|
|
activity.applicationContext,
|
|
|
|
requireComponents.core.store,
|
|
|
|
customTabSessionId
|
|
|
|
)
|
|
|
|
)
|
2019-10-09 01:50:16 +02:00
|
|
|
}
|
2019-08-12 18:31:59 +02:00
|
|
|
}
|
|
|
|
|
2019-11-12 02:10:14 +01:00
|
|
|
consumeFrom(browserFragmentStore) {
|
2019-08-12 18:31:59 +02:00
|
|
|
browserToolbarView.update(it)
|
|
|
|
}
|
2019-09-20 19:28:49 +02:00
|
|
|
|
|
|
|
consumeFrom(components.core.customTabsStore) { state ->
|
|
|
|
getSessionById()
|
|
|
|
?.let { session -> session.customTabConfig?.sessionToken }
|
|
|
|
?.let { token -> state.tabs[token] }
|
|
|
|
?.let { tabState ->
|
|
|
|
hideToolbarFeature.withFeature {
|
|
|
|
it.onTrustedScopesChange(tabState.trustedOrigins)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-08-12 18:31:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun removeSessionIfNeeded(): Boolean {
|
|
|
|
return customTabsIntegration.onBackPressed() || super.removeSessionIfNeeded()
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun navToQuickSettingsSheet(session: Session, sitePermissions: SitePermissions?) {
|
|
|
|
val directions = ExternalAppBrowserFragmentDirections
|
|
|
|
.actionExternalAppBrowserFragmentToQuickSettingsSheetDialogFragment(
|
|
|
|
sessionId = session.id,
|
|
|
|
url = session.url,
|
2020-01-30 20:24:53 +01:00
|
|
|
title = session.title,
|
2019-08-12 18:31:59 +02:00
|
|
|
isSecured = session.securityInfo.secure,
|
|
|
|
sitePermissions = sitePermissions,
|
2020-01-31 13:27:48 +01:00
|
|
|
gravity = getAppropriateLayoutGravity(),
|
|
|
|
certificateName = session.securityInfo.issuer
|
2019-08-12 18:31:59 +02:00
|
|
|
)
|
|
|
|
nav(R.id.externalAppBrowserFragment, directions)
|
|
|
|
}
|
|
|
|
|
2019-09-10 22:29:21 +02:00
|
|
|
override fun navToTrackingProtectionPanel(session: Session) {
|
2019-10-02 06:45:04 +02:00
|
|
|
val useCase = TrackingProtectionUseCases(
|
|
|
|
sessionManager = requireComponents.core.sessionManager,
|
|
|
|
engine = requireComponents.core.engine
|
|
|
|
)
|
|
|
|
useCase.containsException(session) { contains ->
|
|
|
|
val isEnabled = session.trackerBlockingEnabled && !contains
|
|
|
|
val directions =
|
|
|
|
ExternalAppBrowserFragmentDirections
|
|
|
|
.actionExternalAppBrowserFragmentToTrackingProtectionPanelDialogFragment(
|
|
|
|
sessionId = session.id,
|
|
|
|
url = session.url,
|
|
|
|
trackingProtectionEnabled = isEnabled,
|
|
|
|
gravity = getAppropriateLayoutGravity()
|
|
|
|
)
|
|
|
|
nav(R.id.externalAppBrowserFragment, directions)
|
|
|
|
}
|
2019-09-10 22:29:21 +02:00
|
|
|
}
|
|
|
|
|
2019-10-25 06:38:15 +02:00
|
|
|
override fun getContextMenuCandidates(
|
|
|
|
context: Context,
|
|
|
|
view: View
|
|
|
|
): List<ContextMenuCandidate> = CustomTabContextMenuCandidate.defaultCandidates(
|
|
|
|
context,
|
|
|
|
context.components.useCases.contextMenuUseCases,
|
|
|
|
view,
|
2019-12-30 23:43:15 +01:00
|
|
|
FenixSnackbarDelegate(view)
|
2019-10-25 06:38:15 +02:00
|
|
|
)
|
2019-08-12 18:31:59 +02:00
|
|
|
}
|