Refactor ExternalAppBrowserActivity and ExternalAppBrowserFragment to not use Session(Manager).
This commit is contained in:
parent
b419ff82af
commit
023ddcc131
|
@ -184,6 +184,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler,
|
|||
protected var webAppToolbarShouldBeVisible = true
|
||||
|
||||
private val sharedViewModel: SharedViewModel by activityViewModels()
|
||||
private val homeViewModel: HomeScreenViewModel by activityViewModels()
|
||||
|
||||
@VisibleForTesting
|
||||
internal val onboarding by lazy { FenixOnboarding(requireContext()) }
|
||||
|
@ -220,7 +221,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler,
|
|||
}
|
||||
|
||||
final override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
browserInitialized = initializeUI(view) != null
|
||||
initializeUI(view)
|
||||
|
||||
if (customTabSessionId == null) {
|
||||
// We currently only need this observer to navigate to home
|
||||
|
@ -238,12 +239,19 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler,
|
|||
requireContext().accessibilityManager.addAccessibilityStateChangeListener(this)
|
||||
}
|
||||
|
||||
private val homeViewModel: HomeScreenViewModel by activityViewModels()
|
||||
private fun initializeUI(view: View) {
|
||||
val tab = getCurrentTab()
|
||||
browserInitialized = if (tab != null) {
|
||||
initializeUI(view, tab)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("ComplexMethod", "LongMethod")
|
||||
@CallSuper
|
||||
@VisibleForTesting
|
||||
internal open fun initializeUI(view: View): Session? {
|
||||
internal open fun initializeUI(view: View, tab: SessionState) {
|
||||
val context = requireContext()
|
||||
val sessionManager = context.components.core.sessionManager
|
||||
val store = context.components.core.store
|
||||
|
@ -260,456 +268,454 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler,
|
|||
beginAnimateInIfNecessary()
|
||||
}
|
||||
|
||||
return getSessionById()?.also { _ ->
|
||||
val openInFenixIntent = Intent(context, IntentReceiverActivity::class.java).apply {
|
||||
action = Intent.ACTION_VIEW
|
||||
putExtra(HomeActivity.OPEN_TO_BROWSER, true)
|
||||
}
|
||||
val openInFenixIntent = Intent(context, IntentReceiverActivity::class.java).apply {
|
||||
action = Intent.ACTION_VIEW
|
||||
putExtra(HomeActivity.OPEN_TO_BROWSER, true)
|
||||
}
|
||||
|
||||
val readerMenuController = DefaultReaderModeController(
|
||||
readerViewFeature,
|
||||
view.readerViewControlsBar,
|
||||
isPrivate = activity.browsingModeManager.mode.isPrivate
|
||||
)
|
||||
val browserToolbarController = DefaultBrowserToolbarController(
|
||||
store = store,
|
||||
activity = activity,
|
||||
navController = findNavController(),
|
||||
metrics = requireComponents.analytics.metrics,
|
||||
readerModeController = readerMenuController,
|
||||
sessionManager = requireComponents.core.sessionManager,
|
||||
engineView = engineView,
|
||||
homeViewModel = homeViewModel,
|
||||
customTabSession = customTabSessionId?.let { sessionManager.findSessionById(it) },
|
||||
onTabCounterClicked = {
|
||||
thumbnailsFeature.get()?.requestScreenshot()
|
||||
findNavController().nav(
|
||||
R.id.browserFragment,
|
||||
BrowserFragmentDirections.actionGlobalTabTrayDialogFragment()
|
||||
)
|
||||
},
|
||||
onCloseTab = { closedSession ->
|
||||
val tab = store.state.findTab(closedSession.id) ?: return@DefaultBrowserToolbarController
|
||||
|
||||
val snackbarMessage = if (tab.content.private) {
|
||||
requireContext().getString(R.string.snackbar_private_tab_closed)
|
||||
} else {
|
||||
requireContext().getString(R.string.snackbar_tab_closed)
|
||||
}
|
||||
|
||||
viewLifecycleOwner.lifecycleScope.allowUndo(
|
||||
requireView().browserLayout,
|
||||
snackbarMessage,
|
||||
requireContext().getString(R.string.snackbar_deleted_undo),
|
||||
{
|
||||
requireComponents.useCases.tabsUseCases.undo.invoke()
|
||||
},
|
||||
paddedForBottomToolbar = true,
|
||||
operation = { }
|
||||
)
|
||||
}
|
||||
)
|
||||
val browserToolbarMenuController = DefaultBrowserToolbarMenuController(
|
||||
activity = activity,
|
||||
navController = findNavController(),
|
||||
metrics = requireComponents.analytics.metrics,
|
||||
settings = context.settings(),
|
||||
readerModeController = readerMenuController,
|
||||
sessionManager = requireComponents.core.sessionManager,
|
||||
sessionFeature = sessionFeature,
|
||||
findInPageLauncher = { findInPageIntegration.withFeature { it.launch() } },
|
||||
swipeRefresh = swipeRefresh,
|
||||
browserAnimator = browserAnimator,
|
||||
customTabSession = customTabSessionId?.let { sessionManager.findSessionById(it) },
|
||||
openInFenixIntent = openInFenixIntent,
|
||||
bookmarkTapped = { url: String, title: String ->
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
bookmarkTapped(url, title)
|
||||
}
|
||||
},
|
||||
scope = viewLifecycleOwner.lifecycleScope,
|
||||
tabCollectionStorage = requireComponents.core.tabCollectionStorage,
|
||||
topSitesStorage = requireComponents.core.topSitesStorage,
|
||||
browserStore = store
|
||||
)
|
||||
|
||||
_browserInteractor = BrowserInteractor(
|
||||
browserToolbarController,
|
||||
browserToolbarMenuController
|
||||
)
|
||||
|
||||
_browserToolbarView = BrowserToolbarView(
|
||||
container = view.browserLayout,
|
||||
toolbarPosition = context.settings().toolbarPosition,
|
||||
interactor = browserInteractor,
|
||||
customTabSession = customTabSessionId?.let { sessionManager.findSessionById(it) },
|
||||
lifecycleOwner = viewLifecycleOwner
|
||||
)
|
||||
|
||||
toolbarIntegration.set(
|
||||
feature = browserToolbarView.toolbarIntegration,
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
findInPageIntegration.set(
|
||||
feature = FindInPageIntegration(
|
||||
store = store,
|
||||
sessionId = customTabSessionId,
|
||||
stub = view.stubFindInPage,
|
||||
engineView = view.engineView,
|
||||
toolbar = browserToolbarView.view
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
browserToolbarView.view.display.setOnSiteSecurityClickedListener {
|
||||
showQuickSettingsDialog()
|
||||
}
|
||||
|
||||
browserToolbarView.view.display.setOnTrackingProtectionClickedListener {
|
||||
context.metrics.track(Event.TrackingProtectionIconPressed)
|
||||
showTrackingProtectionPanel()
|
||||
}
|
||||
|
||||
contextMenuFeature.set(
|
||||
feature = ContextMenuFeature(
|
||||
fragmentManager = parentFragmentManager,
|
||||
store = store,
|
||||
candidates = getContextMenuCandidates(context, view.browserLayout),
|
||||
engineView = view.engineView,
|
||||
useCases = context.components.useCases.contextMenuUseCases,
|
||||
tabId = customTabSessionId
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
val allowScreenshotsInPrivateMode = context.settings().allowScreenshotsInPrivateMode
|
||||
secureWindowFeature.set(
|
||||
feature = SecureWindowFeature(
|
||||
window = requireActivity().window,
|
||||
store = store,
|
||||
customTabId = customTabSessionId,
|
||||
isSecure = { !allowScreenshotsInPrivateMode && it.content.private }
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
if (newMediaSessionApi) {
|
||||
fullScreenMediaSessionFeature.set(
|
||||
feature = MediaSessionFullscreenFeature(
|
||||
requireActivity(),
|
||||
context.components.core.store
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
val readerMenuController = DefaultReaderModeController(
|
||||
readerViewFeature,
|
||||
view.readerViewControlsBar,
|
||||
isPrivate = activity.browsingModeManager.mode.isPrivate
|
||||
)
|
||||
val browserToolbarController = DefaultBrowserToolbarController(
|
||||
store = store,
|
||||
activity = activity,
|
||||
navController = findNavController(),
|
||||
metrics = requireComponents.analytics.metrics,
|
||||
readerModeController = readerMenuController,
|
||||
sessionManager = requireComponents.core.sessionManager,
|
||||
engineView = engineView,
|
||||
homeViewModel = homeViewModel,
|
||||
customTabSession = customTabSessionId?.let { sessionManager.findSessionById(it) },
|
||||
onTabCounterClicked = {
|
||||
thumbnailsFeature.get()?.requestScreenshot()
|
||||
findNavController().nav(
|
||||
R.id.browserFragment,
|
||||
BrowserFragmentDirections.actionGlobalTabTrayDialogFragment()
|
||||
)
|
||||
} else {
|
||||
fullScreenMediaFeature.set(
|
||||
feature = MediaFullscreenOrientationFeature(
|
||||
requireActivity(),
|
||||
context.components.core.store
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
},
|
||||
onCloseTab = { closedSession ->
|
||||
val closedTab = store.state.findTab(closedSession.id) ?: return@DefaultBrowserToolbarController
|
||||
|
||||
val snackbarMessage = if (closedTab.content.private) {
|
||||
requireContext().getString(R.string.snackbar_private_tab_closed)
|
||||
} else {
|
||||
requireContext().getString(R.string.snackbar_tab_closed)
|
||||
}
|
||||
|
||||
viewLifecycleOwner.lifecycleScope.allowUndo(
|
||||
requireView().browserLayout,
|
||||
snackbarMessage,
|
||||
requireContext().getString(R.string.snackbar_deleted_undo),
|
||||
{
|
||||
requireComponents.useCases.tabsUseCases.undo.invoke()
|
||||
},
|
||||
paddedForBottomToolbar = true,
|
||||
operation = { }
|
||||
)
|
||||
}
|
||||
|
||||
val downloadFeature = DownloadsFeature(
|
||||
context.applicationContext,
|
||||
store = store,
|
||||
useCases = context.components.useCases.downloadUseCases,
|
||||
fragmentManager = childFragmentManager,
|
||||
tabId = customTabSessionId,
|
||||
downloadManager = FetchDownloadManager(
|
||||
context.applicationContext,
|
||||
store,
|
||||
DownloadService::class
|
||||
),
|
||||
shouldForwardToThirdParties = {
|
||||
PreferenceManager.getDefaultSharedPreferences(context).getBoolean(
|
||||
context.getPreferenceKey(R.string.pref_key_external_download_manager), false
|
||||
)
|
||||
},
|
||||
promptsStyling = DownloadsFeature.PromptsStyling(
|
||||
gravity = Gravity.BOTTOM,
|
||||
shouldWidthMatchParent = true,
|
||||
positiveButtonBackgroundColor = ThemeManager.resolveAttribute(
|
||||
R.attr.accent,
|
||||
context
|
||||
),
|
||||
positiveButtonTextColor = ThemeManager.resolveAttribute(
|
||||
R.attr.contrastText,
|
||||
context
|
||||
),
|
||||
positiveButtonRadius = (resources.getDimensionPixelSize(R.dimen.tab_corner_radius)).toFloat()
|
||||
),
|
||||
onNeedToRequestPermissions = { permissions ->
|
||||
requestPermissions(permissions, REQUEST_CODE_DOWNLOAD_PERMISSIONS)
|
||||
)
|
||||
val browserToolbarMenuController = DefaultBrowserToolbarMenuController(
|
||||
activity = activity,
|
||||
navController = findNavController(),
|
||||
metrics = requireComponents.analytics.metrics,
|
||||
settings = context.settings(),
|
||||
readerModeController = readerMenuController,
|
||||
sessionManager = requireComponents.core.sessionManager,
|
||||
sessionFeature = sessionFeature,
|
||||
findInPageLauncher = { findInPageIntegration.withFeature { it.launch() } },
|
||||
swipeRefresh = swipeRefresh,
|
||||
browserAnimator = browserAnimator,
|
||||
customTabSession = customTabSessionId?.let { sessionManager.findSessionById(it) },
|
||||
openInFenixIntent = openInFenixIntent,
|
||||
bookmarkTapped = { url: String, title: String ->
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
bookmarkTapped(url, title)
|
||||
}
|
||||
)
|
||||
},
|
||||
scope = viewLifecycleOwner.lifecycleScope,
|
||||
tabCollectionStorage = requireComponents.core.tabCollectionStorage,
|
||||
topSitesStorage = requireComponents.core.topSitesStorage,
|
||||
browserStore = store
|
||||
)
|
||||
|
||||
downloadFeature.onDownloadStopped = { downloadState, _, downloadJobStatus ->
|
||||
// If the download is just paused, don't show any in-app notification
|
||||
if (downloadJobStatus == DownloadState.Status.COMPLETED ||
|
||||
downloadJobStatus == DownloadState.Status.FAILED
|
||||
) {
|
||||
_browserInteractor = BrowserInteractor(
|
||||
browserToolbarController,
|
||||
browserToolbarMenuController
|
||||
)
|
||||
|
||||
saveDownloadDialogState(
|
||||
downloadState.sessionId,
|
||||
downloadState,
|
||||
downloadJobStatus
|
||||
)
|
||||
_browserToolbarView = BrowserToolbarView(
|
||||
container = view.browserLayout,
|
||||
toolbarPosition = context.settings().toolbarPosition,
|
||||
interactor = browserInteractor,
|
||||
customTabSession = customTabSessionId?.let { sessionManager.findSessionById(it) },
|
||||
lifecycleOwner = viewLifecycleOwner
|
||||
)
|
||||
|
||||
val dynamicDownloadDialog = DynamicDownloadDialog(
|
||||
container = view.browserLayout,
|
||||
downloadState = downloadState,
|
||||
metrics = requireComponents.analytics.metrics,
|
||||
didFail = downloadJobStatus == DownloadState.Status.FAILED,
|
||||
tryAgain = downloadFeature::tryAgain,
|
||||
onCannotOpenFile = {
|
||||
FenixSnackbar.make(
|
||||
view = view.browserLayout,
|
||||
duration = Snackbar.LENGTH_SHORT,
|
||||
isDisplayedWithBrowserToolbar = true
|
||||
)
|
||||
.setText(context.getString(R.string.mozac_feature_downloads_could_not_open_file))
|
||||
.show()
|
||||
},
|
||||
view = view.viewDynamicDownloadDialog,
|
||||
toolbarHeight = toolbarHeight,
|
||||
onDismiss = { sharedViewModel.downloadDialogState.remove(downloadState.sessionId) }
|
||||
)
|
||||
toolbarIntegration.set(
|
||||
feature = browserToolbarView.toolbarIntegration,
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
// Don't show the dialog if we aren't in the tab that started the download
|
||||
if (downloadState.sessionId == sessionManager.selectedSession?.id) {
|
||||
dynamicDownloadDialog.show()
|
||||
browserToolbarView.expand()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resumeDownloadDialogState(
|
||||
sessionManager.selectedSession?.id,
|
||||
store, view, context, toolbarHeight
|
||||
)
|
||||
|
||||
downloadsFeature.set(
|
||||
downloadFeature,
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
pipFeature = PictureInPictureFeature(
|
||||
findInPageIntegration.set(
|
||||
feature = FindInPageIntegration(
|
||||
store = store,
|
||||
activity = requireActivity(),
|
||||
crashReporting = context.components.analytics.crashReporter,
|
||||
sessionId = customTabSessionId,
|
||||
stub = view.stubFindInPage,
|
||||
engineView = view.engineView,
|
||||
toolbar = browserToolbarView.view
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
browserToolbarView.view.display.setOnSiteSecurityClickedListener {
|
||||
showQuickSettingsDialog()
|
||||
}
|
||||
|
||||
browserToolbarView.view.display.setOnTrackingProtectionClickedListener {
|
||||
context.metrics.track(Event.TrackingProtectionIconPressed)
|
||||
showTrackingProtectionPanel()
|
||||
}
|
||||
|
||||
contextMenuFeature.set(
|
||||
feature = ContextMenuFeature(
|
||||
fragmentManager = parentFragmentManager,
|
||||
store = store,
|
||||
candidates = getContextMenuCandidates(context, view.browserLayout),
|
||||
engineView = view.engineView,
|
||||
useCases = context.components.useCases.contextMenuUseCases,
|
||||
tabId = customTabSessionId
|
||||
)
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
appLinksFeature.set(
|
||||
feature = AppLinksFeature(
|
||||
context,
|
||||
store = store,
|
||||
sessionId = customTabSessionId,
|
||||
fragmentManager = parentFragmentManager,
|
||||
launchInApp = { context.settings().openLinksInExternalApp },
|
||||
loadUrlUseCase = context.components.useCases.sessionUseCases.loadUrl
|
||||
val allowScreenshotsInPrivateMode = context.settings().allowScreenshotsInPrivateMode
|
||||
secureWindowFeature.set(
|
||||
feature = SecureWindowFeature(
|
||||
window = requireActivity().window,
|
||||
store = store,
|
||||
customTabId = customTabSessionId,
|
||||
isSecure = { !allowScreenshotsInPrivateMode && it.content.private }
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
if (newMediaSessionApi) {
|
||||
fullScreenMediaSessionFeature.set(
|
||||
feature = MediaSessionFullscreenFeature(
|
||||
requireActivity(),
|
||||
context.components.core.store
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
} else {
|
||||
fullScreenMediaFeature.set(
|
||||
feature = MediaFullscreenOrientationFeature(
|
||||
requireActivity(),
|
||||
context.components.core.store
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
}
|
||||
|
||||
promptsFeature.set(
|
||||
feature = PromptFeature(
|
||||
fragment = this,
|
||||
store = store,
|
||||
customTabId = customTabSessionId,
|
||||
fragmentManager = parentFragmentManager,
|
||||
loginValidationDelegate = DefaultLoginValidationDelegate(
|
||||
context.components.core.lazyPasswordsStorage
|
||||
),
|
||||
isSaveLoginEnabled = {
|
||||
context.settings().shouldPromptToSaveLogins
|
||||
val downloadFeature = DownloadsFeature(
|
||||
context.applicationContext,
|
||||
store = store,
|
||||
useCases = context.components.useCases.downloadUseCases,
|
||||
fragmentManager = childFragmentManager,
|
||||
tabId = customTabSessionId,
|
||||
downloadManager = FetchDownloadManager(
|
||||
context.applicationContext,
|
||||
store,
|
||||
DownloadService::class
|
||||
),
|
||||
shouldForwardToThirdParties = {
|
||||
PreferenceManager.getDefaultSharedPreferences(context).getBoolean(
|
||||
context.getPreferenceKey(R.string.pref_key_external_download_manager), false
|
||||
)
|
||||
},
|
||||
promptsStyling = DownloadsFeature.PromptsStyling(
|
||||
gravity = Gravity.BOTTOM,
|
||||
shouldWidthMatchParent = true,
|
||||
positiveButtonBackgroundColor = ThemeManager.resolveAttribute(
|
||||
R.attr.accent,
|
||||
context
|
||||
),
|
||||
positiveButtonTextColor = ThemeManager.resolveAttribute(
|
||||
R.attr.contrastText,
|
||||
context
|
||||
),
|
||||
positiveButtonRadius = (resources.getDimensionPixelSize(R.dimen.tab_corner_radius)).toFloat()
|
||||
),
|
||||
onNeedToRequestPermissions = { permissions ->
|
||||
requestPermissions(permissions, REQUEST_CODE_DOWNLOAD_PERMISSIONS)
|
||||
}
|
||||
)
|
||||
|
||||
downloadFeature.onDownloadStopped = { downloadState, _, downloadJobStatus ->
|
||||
// If the download is just paused, don't show any in-app notification
|
||||
if (downloadJobStatus == DownloadState.Status.COMPLETED ||
|
||||
downloadJobStatus == DownloadState.Status.FAILED
|
||||
) {
|
||||
|
||||
saveDownloadDialogState(
|
||||
downloadState.sessionId,
|
||||
downloadState,
|
||||
downloadJobStatus
|
||||
)
|
||||
|
||||
val dynamicDownloadDialog = DynamicDownloadDialog(
|
||||
container = view.browserLayout,
|
||||
downloadState = downloadState,
|
||||
metrics = requireComponents.analytics.metrics,
|
||||
didFail = downloadJobStatus == DownloadState.Status.FAILED,
|
||||
tryAgain = downloadFeature::tryAgain,
|
||||
onCannotOpenFile = {
|
||||
FenixSnackbar.make(
|
||||
view = view.browserLayout,
|
||||
duration = Snackbar.LENGTH_SHORT,
|
||||
isDisplayedWithBrowserToolbar = true
|
||||
)
|
||||
.setText(context.getString(R.string.mozac_feature_downloads_could_not_open_file))
|
||||
.show()
|
||||
},
|
||||
loginExceptionStorage = context.components.core.loginExceptionStorage,
|
||||
shareDelegate = object : ShareDelegate {
|
||||
override fun showShareSheet(
|
||||
context: Context,
|
||||
shareData: ShareData,
|
||||
onDismiss: () -> Unit,
|
||||
onSuccess: () -> Unit
|
||||
) {
|
||||
val directions = NavGraphDirections.actionGlobalShareFragment(
|
||||
data = arrayOf(shareData),
|
||||
showPage = true,
|
||||
sessionId = getSessionById()?.id
|
||||
)
|
||||
findNavController().navigate(directions)
|
||||
}
|
||||
},
|
||||
onNeedToRequestPermissions = { permissions ->
|
||||
requestPermissions(permissions, REQUEST_CODE_PROMPT_PERMISSIONS)
|
||||
},
|
||||
loginPickerView = loginSelectBar,
|
||||
onManageLogins = {
|
||||
browserAnimator.captureEngineViewAndDrawStatically {
|
||||
val directions =
|
||||
NavGraphDirections.actionGlobalSavedLoginsAuthFragment()
|
||||
findNavController().navigate(directions)
|
||||
}
|
||||
view = view.viewDynamicDownloadDialog,
|
||||
toolbarHeight = toolbarHeight,
|
||||
onDismiss = { sharedViewModel.downloadDialogState.remove(downloadState.sessionId) }
|
||||
)
|
||||
|
||||
// Don't show the dialog if we aren't in the tab that started the download
|
||||
if (downloadState.sessionId == sessionManager.selectedSession?.id) {
|
||||
dynamicDownloadDialog.show()
|
||||
browserToolbarView.expand()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resumeDownloadDialogState(
|
||||
sessionManager.selectedSession?.id,
|
||||
store, view, context, toolbarHeight
|
||||
)
|
||||
|
||||
downloadsFeature.set(
|
||||
downloadFeature,
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
pipFeature = PictureInPictureFeature(
|
||||
store = store,
|
||||
activity = requireActivity(),
|
||||
crashReporting = context.components.analytics.crashReporter,
|
||||
tabId = customTabSessionId
|
||||
)
|
||||
|
||||
appLinksFeature.set(
|
||||
feature = AppLinksFeature(
|
||||
context,
|
||||
store = store,
|
||||
sessionId = customTabSessionId,
|
||||
fragmentManager = parentFragmentManager,
|
||||
launchInApp = { context.settings().openLinksInExternalApp },
|
||||
loadUrlUseCase = context.components.useCases.sessionUseCases.loadUrl
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
promptsFeature.set(
|
||||
feature = PromptFeature(
|
||||
fragment = this,
|
||||
store = store,
|
||||
customTabId = customTabSessionId,
|
||||
fragmentManager = parentFragmentManager,
|
||||
loginValidationDelegate = DefaultLoginValidationDelegate(
|
||||
context.components.core.lazyPasswordsStorage
|
||||
),
|
||||
isSaveLoginEnabled = {
|
||||
context.settings().shouldPromptToSaveLogins
|
||||
},
|
||||
loginExceptionStorage = context.components.core.loginExceptionStorage,
|
||||
shareDelegate = object : ShareDelegate {
|
||||
override fun showShareSheet(
|
||||
context: Context,
|
||||
shareData: ShareData,
|
||||
onDismiss: () -> Unit,
|
||||
onSuccess: () -> Unit
|
||||
) {
|
||||
val directions = NavGraphDirections.actionGlobalShareFragment(
|
||||
data = arrayOf(shareData),
|
||||
showPage = true,
|
||||
sessionId = getSessionById()?.id
|
||||
)
|
||||
findNavController().navigate(directions)
|
||||
}
|
||||
},
|
||||
onNeedToRequestPermissions = { permissions ->
|
||||
requestPermissions(permissions, REQUEST_CODE_PROMPT_PERMISSIONS)
|
||||
},
|
||||
loginPickerView = loginSelectBar,
|
||||
onManageLogins = {
|
||||
browserAnimator.captureEngineViewAndDrawStatically {
|
||||
val directions =
|
||||
NavGraphDirections.actionGlobalSavedLoginsAuthFragment()
|
||||
findNavController().navigate(directions)
|
||||
}
|
||||
}
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
sessionFeature.set(
|
||||
feature = SessionFeature(
|
||||
requireComponents.core.store,
|
||||
requireComponents.useCases.sessionUseCases.goBack,
|
||||
view.engineView,
|
||||
customTabSessionId
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
searchFeature.set(
|
||||
feature = SearchFeature(store, customTabSessionId) { request, tabId ->
|
||||
val parentSession = sessionManager.findSessionById(tabId)
|
||||
val useCase = if (request.isPrivate) {
|
||||
requireComponents.useCases.searchUseCases.newPrivateTabSearch
|
||||
} else {
|
||||
requireComponents.useCases.searchUseCases.newTabSearch
|
||||
}
|
||||
|
||||
if (parentSession?.isCustomTabSession() == true) {
|
||||
useCase.invoke(request.query)
|
||||
requireActivity().startActivity(openInFenixIntent)
|
||||
} else {
|
||||
useCase.invoke(request.query, parentSessionId = parentSession?.id)
|
||||
}
|
||||
},
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
val accentHighContrastColor =
|
||||
ThemeManager.resolveAttribute(R.attr.accentHighContrast, context)
|
||||
|
||||
sitePermissionsFeature.set(
|
||||
feature = SitePermissionsFeature(
|
||||
context = context,
|
||||
storage = context.components.core.permissionStorage.permissionsStorage,
|
||||
fragmentManager = parentFragmentManager,
|
||||
promptsStyling = SitePermissionsFeature.PromptsStyling(
|
||||
gravity = getAppropriateLayoutGravity(),
|
||||
shouldWidthMatchParent = true,
|
||||
positiveButtonBackgroundColor = accentHighContrastColor,
|
||||
positiveButtonTextColor = R.color.photonWhite
|
||||
),
|
||||
sessionId = customTabSessionId,
|
||||
onNeedToRequestPermissions = { permissions ->
|
||||
requestPermissions(permissions, REQUEST_CODE_APP_PERMISSIONS)
|
||||
},
|
||||
onShouldShowRequestPermissionRationale = {
|
||||
shouldShowRequestPermissionRationale(
|
||||
it
|
||||
)
|
||||
},
|
||||
store = store
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
sitePermissionWifiIntegration.set(
|
||||
feature = SitePermissionsWifiIntegration(
|
||||
settings = context.settings(),
|
||||
wifiConnectionMonitor = context.components.wifiConnectionMonitor
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
if (FeatureFlags.webAuthFeature) {
|
||||
webAuthnFeature.set(
|
||||
feature = WebAuthnFeature(
|
||||
engine = requireComponents.core.engine,
|
||||
activity = requireActivity()
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
}
|
||||
|
||||
sessionFeature.set(
|
||||
feature = SessionFeature(
|
||||
context.settings().setSitePermissionSettingListener(viewLifecycleOwner) {
|
||||
// If the user connects to WIFI while on the BrowserFragment, this will update the
|
||||
// SitePermissionsRules (specifically autoplay) accordingly
|
||||
runIfFragmentIsAttached {
|
||||
assignSitePermissionsRules()
|
||||
}
|
||||
}
|
||||
assignSitePermissionsRules()
|
||||
|
||||
fullScreenFeature.set(
|
||||
feature = FullScreenFeature(
|
||||
requireComponents.core.store,
|
||||
requireComponents.useCases.sessionUseCases,
|
||||
customTabSessionId,
|
||||
::viewportFitChange,
|
||||
::fullScreenChanged
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
expandToolbarOnNavigation(store)
|
||||
|
||||
store.flowScoped(viewLifecycleOwner) { flow ->
|
||||
flow.mapNotNull { state -> state.findTabOrCustomTabOrSelectedTab(customTabSessionId) }
|
||||
.ifChanged { tab -> tab.content.pictureInPictureEnabled }
|
||||
.collect { tab -> pipModeChanged(tab) }
|
||||
}
|
||||
|
||||
view.swipeRefresh.isEnabled = shouldPullToRefreshBeEnabled(false)
|
||||
|
||||
if (view.swipeRefresh.isEnabled) {
|
||||
val primaryTextColor =
|
||||
ThemeManager.resolveAttribute(R.attr.primaryText, context)
|
||||
view.swipeRefresh.setColorSchemeColors(primaryTextColor)
|
||||
swipeRefreshFeature.set(
|
||||
feature = SwipeRefreshFeature(
|
||||
requireComponents.core.store,
|
||||
requireComponents.useCases.sessionUseCases.goBack,
|
||||
view.engineView,
|
||||
context.components.useCases.sessionUseCases.reload,
|
||||
view.swipeRefresh,
|
||||
customTabSessionId
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
searchFeature.set(
|
||||
feature = SearchFeature(store, customTabSessionId) { request, tabId ->
|
||||
val parentSession = sessionManager.findSessionById(tabId)
|
||||
val useCase = if (request.isPrivate) {
|
||||
requireComponents.useCases.searchUseCases.newPrivateTabSearch
|
||||
} else {
|
||||
requireComponents.useCases.searchUseCases.newTabSearch
|
||||
}
|
||||
|
||||
if (parentSession?.isCustomTabSession() == true) {
|
||||
useCase.invoke(request.query)
|
||||
requireActivity().startActivity(openInFenixIntent)
|
||||
} else {
|
||||
useCase.invoke(request.query, parentSessionId = parentSession?.id)
|
||||
}
|
||||
},
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
val accentHighContrastColor =
|
||||
ThemeManager.resolveAttribute(R.attr.accentHighContrast, context)
|
||||
|
||||
sitePermissionsFeature.set(
|
||||
feature = SitePermissionsFeature(
|
||||
context = context,
|
||||
storage = context.components.core.permissionStorage.permissionsStorage,
|
||||
fragmentManager = parentFragmentManager,
|
||||
promptsStyling = SitePermissionsFeature.PromptsStyling(
|
||||
gravity = getAppropriateLayoutGravity(),
|
||||
shouldWidthMatchParent = true,
|
||||
positiveButtonBackgroundColor = accentHighContrastColor,
|
||||
positiveButtonTextColor = R.color.photonWhite
|
||||
),
|
||||
sessionId = customTabSessionId,
|
||||
onNeedToRequestPermissions = { permissions ->
|
||||
requestPermissions(permissions, REQUEST_CODE_APP_PERMISSIONS)
|
||||
},
|
||||
onShouldShowRequestPermissionRationale = {
|
||||
shouldShowRequestPermissionRationale(
|
||||
it
|
||||
)
|
||||
},
|
||||
store = store
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
sitePermissionWifiIntegration.set(
|
||||
feature = SitePermissionsWifiIntegration(
|
||||
settings = context.settings(),
|
||||
wifiConnectionMonitor = context.components.wifiConnectionMonitor
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
if (FeatureFlags.webAuthFeature) {
|
||||
webAuthnFeature.set(
|
||||
feature = WebAuthnFeature(
|
||||
engine = requireComponents.core.engine,
|
||||
activity = requireActivity()
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
}
|
||||
|
||||
context.settings().setSitePermissionSettingListener(viewLifecycleOwner) {
|
||||
// If the user connects to WIFI while on the BrowserFragment, this will update the
|
||||
// SitePermissionsRules (specifically autoplay) accordingly
|
||||
runIfFragmentIsAttached {
|
||||
assignSitePermissionsRules()
|
||||
}
|
||||
}
|
||||
assignSitePermissionsRules()
|
||||
|
||||
fullScreenFeature.set(
|
||||
feature = FullScreenFeature(
|
||||
requireComponents.core.store,
|
||||
requireComponents.useCases.sessionUseCases,
|
||||
customTabSessionId,
|
||||
::viewportFitChange,
|
||||
::fullScreenChanged
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
expandToolbarOnNavigation(store)
|
||||
|
||||
store.flowScoped(viewLifecycleOwner) { flow ->
|
||||
flow.mapNotNull { state -> state.findTabOrCustomTabOrSelectedTab(customTabSessionId) }
|
||||
.ifChanged { tab -> tab.content.pictureInPictureEnabled }
|
||||
.collect { tab -> pipModeChanged(tab) }
|
||||
}
|
||||
|
||||
view.swipeRefresh.isEnabled = shouldPullToRefreshBeEnabled(false)
|
||||
|
||||
if (view.swipeRefresh.isEnabled) {
|
||||
val primaryTextColor =
|
||||
ThemeManager.resolveAttribute(R.attr.primaryText, context)
|
||||
view.swipeRefresh.setColorSchemeColors(primaryTextColor)
|
||||
swipeRefreshFeature.set(
|
||||
feature = SwipeRefreshFeature(
|
||||
requireComponents.core.store,
|
||||
context.components.useCases.sessionUseCases.reload,
|
||||
view.swipeRefresh,
|
||||
customTabSessionId
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
}
|
||||
|
||||
webchannelIntegration.set(
|
||||
feature = FxaWebChannelFeature(
|
||||
requireContext(),
|
||||
customTabSessionId,
|
||||
requireComponents.core.engine,
|
||||
requireComponents.core.store,
|
||||
requireComponents.backgroundServices.accountManager,
|
||||
requireComponents.backgroundServices.serverConfig,
|
||||
setOf(FxaCapability.CHOOSE_WHAT_TO_SYNC)
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
initializeEngineView(toolbarHeight)
|
||||
}
|
||||
|
||||
webchannelIntegration.set(
|
||||
feature = FxaWebChannelFeature(
|
||||
requireContext(),
|
||||
customTabSessionId,
|
||||
requireComponents.core.engine,
|
||||
requireComponents.core.store,
|
||||
requireComponents.backgroundServices.accountManager,
|
||||
requireComponents.backgroundServices.serverConfig,
|
||||
setOf(FxaCapability.CHOOSE_WHAT_TO_SYNC)
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
initializeEngineView(toolbarHeight)
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
@ -928,9 +934,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler,
|
|||
resumeDownloadDialogState(selectedTab.id, context.components.core.store, view, context, toolbarHeight)
|
||||
}
|
||||
} else {
|
||||
view?.let { view ->
|
||||
browserInitialized = initializeUI(view) != null
|
||||
}
|
||||
view?.let { view -> initializeUI(view) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1070,7 +1074,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler,
|
|||
sitePermissions: SitePermissions?
|
||||
)
|
||||
|
||||
protected abstract fun navToTrackingProtectionPanel(session: Session)
|
||||
protected abstract fun navToTrackingProtectionPanel(tab: SessionState)
|
||||
|
||||
/**
|
||||
* Returns the layout [android.view.Gravity] for the quick settings and ETP dialog.
|
||||
|
@ -1108,9 +1112,9 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler,
|
|||
}
|
||||
|
||||
private fun showTrackingProtectionPanel() {
|
||||
val session = getSessionById() ?: return
|
||||
val tab = getCurrentTab() ?: return
|
||||
view?.let {
|
||||
navToTrackingProtectionPanel(session)
|
||||
navToTrackingProtectionPanel(tab)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ import com.google.android.material.snackbar.Snackbar
|
|||
import kotlinx.android.synthetic.main.fragment_browser.*
|
||||
import kotlinx.android.synthetic.main.fragment_browser.view.*
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import mozilla.components.browser.session.Session
|
||||
import mozilla.components.browser.state.selector.findTab
|
||||
import mozilla.components.browser.state.state.TabSessionState
|
||||
import mozilla.components.browser.state.state.SessionState
|
||||
|
@ -56,107 +55,107 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
|
|||
private var pwaOnboardingObserver: PwaOnboardingObserver? = null
|
||||
|
||||
@Suppress("LongMethod")
|
||||
override fun initializeUI(view: View): Session? {
|
||||
override fun initializeUI(view: View, tab: SessionState) {
|
||||
super.initializeUI(view, tab)
|
||||
|
||||
val context = requireContext()
|
||||
val components = context.components
|
||||
|
||||
return super.initializeUI(view)?.also {
|
||||
if (context.settings().isSwipeToolbarToSwitchTabsEnabled) {
|
||||
gestureLayout.addGestureListener(
|
||||
ToolbarGestureHandler(
|
||||
activity = requireActivity(),
|
||||
contentLayout = browserLayout,
|
||||
tabPreview = tabPreview,
|
||||
toolbarLayout = browserToolbarView.view,
|
||||
store = components.core.store,
|
||||
sessionManager = components.core.sessionManager
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val readerModeAction =
|
||||
BrowserToolbar.ToggleButton(
|
||||
image = AppCompatResources.getDrawable(requireContext(), R.drawable.ic_readermode)!!,
|
||||
imageSelected =
|
||||
AppCompatResources.getDrawable(requireContext(), R.drawable.ic_readermode_selected)!!,
|
||||
contentDescription = requireContext().getString(R.string.browser_menu_read),
|
||||
contentDescriptionSelected = requireContext().getString(R.string.browser_menu_read_close),
|
||||
visible = {
|
||||
readerModeAvailable
|
||||
},
|
||||
selected = getSessionById()?.let {
|
||||
activity?.components?.core?.store?.state?.findTab(it.id)?.readerState?.active
|
||||
} ?: false,
|
||||
listener = browserInteractor::onReaderModePressed
|
||||
)
|
||||
|
||||
browserToolbarView.view.addPageAction(readerModeAction)
|
||||
|
||||
thumbnailsFeature.set(
|
||||
feature = BrowserThumbnails(context, view.engineView, components.core.store),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
readerViewFeature.set(
|
||||
feature = components.strictMode.resetAfter(StrictMode.allowThreadDiskReads()) {
|
||||
ReaderViewFeature(
|
||||
context,
|
||||
components.core.engine,
|
||||
components.core.store,
|
||||
view.readerViewControlsBar
|
||||
) { available, active ->
|
||||
if (available) {
|
||||
components.analytics.metrics.track(Event.ReaderModeAvailable)
|
||||
}
|
||||
|
||||
readerModeAvailable = available
|
||||
readerModeAction.setSelected(active)
|
||||
safeInvalidateBrowserToolbarView()
|
||||
}
|
||||
},
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
windowFeature.set(
|
||||
feature = WindowFeature(
|
||||
if (context.settings().isSwipeToolbarToSwitchTabsEnabled) {
|
||||
gestureLayout.addGestureListener(
|
||||
ToolbarGestureHandler(
|
||||
activity = requireActivity(),
|
||||
contentLayout = browserLayout,
|
||||
tabPreview = tabPreview,
|
||||
toolbarLayout = browserToolbarView.view,
|
||||
store = components.core.store,
|
||||
tabsUseCases = components.useCases.tabsUseCases
|
||||
sessionManager = components.core.sessionManager
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val readerModeAction =
|
||||
BrowserToolbar.ToggleButton(
|
||||
image = AppCompatResources.getDrawable(requireContext(), R.drawable.ic_readermode)!!,
|
||||
imageSelected =
|
||||
AppCompatResources.getDrawable(requireContext(), R.drawable.ic_readermode_selected)!!,
|
||||
contentDescription = requireContext().getString(R.string.browser_menu_read),
|
||||
contentDescriptionSelected = requireContext().getString(R.string.browser_menu_read_close),
|
||||
visible = {
|
||||
readerModeAvailable
|
||||
},
|
||||
selected = getSessionById()?.let {
|
||||
activity?.components?.core?.store?.state?.findTab(it.id)?.readerState?.active
|
||||
} ?: false,
|
||||
listener = browserInteractor::onReaderModePressed
|
||||
)
|
||||
|
||||
browserToolbarView.view.addPageAction(readerModeAction)
|
||||
|
||||
thumbnailsFeature.set(
|
||||
feature = BrowserThumbnails(context, view.engineView, components.core.store),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
readerViewFeature.set(
|
||||
feature = components.strictMode.resetAfter(StrictMode.allowThreadDiskReads()) {
|
||||
ReaderViewFeature(
|
||||
context,
|
||||
components.core.engine,
|
||||
components.core.store,
|
||||
view.readerViewControlsBar
|
||||
) { available, active ->
|
||||
if (available) {
|
||||
components.analytics.metrics.track(Event.ReaderModeAvailable)
|
||||
}
|
||||
|
||||
readerModeAvailable = available
|
||||
readerModeAction.setSelected(active)
|
||||
safeInvalidateBrowserToolbarView()
|
||||
}
|
||||
},
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
windowFeature.set(
|
||||
feature = WindowFeature(
|
||||
store = components.core.store,
|
||||
tabsUseCases = components.useCases.tabsUseCases
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
if (context.settings().shouldShowOpenInAppCfr) {
|
||||
openInAppOnboardingObserver.set(
|
||||
feature = OpenInAppOnboardingObserver(
|
||||
context = context,
|
||||
store = context.components.core.store,
|
||||
lifecycleOwner = this,
|
||||
navController = findNavController(),
|
||||
settings = context.settings(),
|
||||
appLinksUseCases = context.components.useCases.appLinksUseCases,
|
||||
container = browserLayout as ViewGroup
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
}
|
||||
if (context.settings().shouldShowTrackingProtectionCfr) {
|
||||
trackingProtectionOverlayObserver.set(
|
||||
feature = TrackingProtectionOverlay(
|
||||
context = context,
|
||||
store = context.components.core.store,
|
||||
lifecycleOwner = viewLifecycleOwner,
|
||||
settings = context.settings(),
|
||||
metrics = context.components.analytics.metrics,
|
||||
getToolbar = { browserToolbarView.view }
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
if (context.settings().shouldShowOpenInAppCfr) {
|
||||
openInAppOnboardingObserver.set(
|
||||
feature = OpenInAppOnboardingObserver(
|
||||
context = context,
|
||||
store = context.components.core.store,
|
||||
lifecycleOwner = this,
|
||||
navController = findNavController(),
|
||||
settings = context.settings(),
|
||||
appLinksUseCases = context.components.useCases.appLinksUseCases,
|
||||
container = browserLayout as ViewGroup
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
}
|
||||
if (context.settings().shouldShowTrackingProtectionCfr) {
|
||||
trackingProtectionOverlayObserver.set(
|
||||
feature = TrackingProtectionOverlay(
|
||||
context = context,
|
||||
store = context.components.core.store,
|
||||
lifecycleOwner = viewLifecycleOwner,
|
||||
settings = context.settings(),
|
||||
metrics = context.components.analytics.metrics,
|
||||
getToolbar = { browserToolbarView.view }
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,15 +218,15 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
|
|||
nav(R.id.browserFragment, directions)
|
||||
}
|
||||
|
||||
override fun navToTrackingProtectionPanel(session: Session) {
|
||||
override fun navToTrackingProtectionPanel(tab: SessionState) {
|
||||
val navController = findNavController()
|
||||
|
||||
requireComponents.useCases.trackingProtectionUseCases.containsException(session.id) { contains ->
|
||||
val isEnabled = session.trackerBlockingEnabled && !contains
|
||||
requireComponents.useCases.trackingProtectionUseCases.containsException(tab.id) { contains ->
|
||||
val isEnabled = tab.trackingProtection.enabled && !contains
|
||||
val directions =
|
||||
BrowserFragmentDirections.actionBrowserFragmentToTrackingProtectionPanelDialogFragment(
|
||||
sessionId = session.id,
|
||||
url = session.url,
|
||||
sessionId = tab.id,
|
||||
url = tab.content.url,
|
||||
trackingProtectionEnabled = isEnabled,
|
||||
gravity = getAppropriateLayoutGravity()
|
||||
)
|
||||
|
|
|
@ -9,7 +9,6 @@ import androidx.annotation.VisibleForTesting
|
|||
import androidx.navigation.NavDestination
|
||||
import androidx.navigation.NavDirections
|
||||
import kotlinx.android.synthetic.main.activity_home.*
|
||||
import mozilla.components.browser.session.runWithSession
|
||||
import mozilla.components.browser.state.selector.findCustomTab
|
||||
import mozilla.components.browser.state.state.SessionState
|
||||
import mozilla.components.concept.engine.manifest.WebAppManifestParser
|
||||
|
@ -102,12 +101,9 @@ open class ExternalAppBrowserActivity : HomeActivity() {
|
|||
// When this activity finishes, the process is staying around and the session still
|
||||
// exists then remove it now to free all its resources. Once this activity is finished
|
||||
// then there's no way to get back to it other than relaunching it.
|
||||
components.core.sessionManager.runWithSession(getExternalTabId()) { session ->
|
||||
// If the custom tag config has been removed we are opening this in normal browsing
|
||||
if (session.customTabConfig != null) {
|
||||
remove(session)
|
||||
}
|
||||
true
|
||||
val tabId = getExternalTabId()
|
||||
if (tabId != null) {
|
||||
components.useCases.customTabsUseCases.remove(tabId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ import androidx.navigation.fragment.navArgs
|
|||
import kotlinx.android.synthetic.main.component_browser_top_toolbar.*
|
||||
import kotlinx.android.synthetic.main.fragment_browser.*
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import mozilla.components.browser.session.Session
|
||||
import mozilla.components.browser.state.state.SessionState
|
||||
import mozilla.components.concept.engine.manifest.WebAppManifestParser
|
||||
import mozilla.components.concept.engine.manifest.getOrNull
|
||||
|
@ -52,113 +51,109 @@ class ExternalAppBrowserFragment : BaseBrowserFragment(), UserInteractionHandler
|
|||
private val hideToolbarFeature = ViewBoundFeatureWrapper<WebAppHideToolbarFeature>()
|
||||
|
||||
@Suppress("LongMethod", "ComplexMethod")
|
||||
override fun initializeUI(view: View): Session? {
|
||||
return super.initializeUI(view)?.also {
|
||||
val activity = requireActivity()
|
||||
val components = activity.components
|
||||
override fun initializeUI(view: View, tab: SessionState) {
|
||||
super.initializeUI(view, tab)
|
||||
|
||||
val manifest = args.webAppManifest?.let { json ->
|
||||
WebAppManifestParser().parse(json).getOrNull()
|
||||
}
|
||||
val customTabSessionId = customTabSessionId ?: return
|
||||
val activity = requireActivity()
|
||||
val components = activity.components
|
||||
val manifest = args.webAppManifest?.let { json -> WebAppManifestParser().parse(json).getOrNull() }
|
||||
|
||||
customTabSessionId?.let { customTabSessionId ->
|
||||
customTabsIntegration.set(
|
||||
feature = CustomTabsIntegration(
|
||||
sessionManager = requireComponents.core.sessionManager,
|
||||
store = requireComponents.core.store,
|
||||
useCases = requireComponents.useCases.customTabsUseCases,
|
||||
toolbar = toolbar,
|
||||
sessionId = customTabSessionId,
|
||||
activity = activity,
|
||||
onItemTapped = { browserInteractor.onBrowserToolbarMenuItemTapped(it) },
|
||||
isPrivate = it.private,
|
||||
shouldReverseItems = !activity.settings().shouldUseBottomToolbar
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
customTabsIntegration.set(
|
||||
feature = CustomTabsIntegration(
|
||||
sessionManager = requireComponents.core.sessionManager,
|
||||
store = requireComponents.core.store,
|
||||
useCases = requireComponents.useCases.customTabsUseCases,
|
||||
toolbar = toolbar,
|
||||
sessionId = customTabSessionId,
|
||||
activity = activity,
|
||||
onItemTapped = { browserInteractor.onBrowserToolbarMenuItemTapped(it) },
|
||||
isPrivate = tab.content.private,
|
||||
shouldReverseItems = !activity.settings().shouldUseBottomToolbar
|
||||
),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
windowFeature.set(
|
||||
feature = CustomTabWindowFeature(
|
||||
activity,
|
||||
components.core.store,
|
||||
customTabSessionId
|
||||
) { uri ->
|
||||
val intent =
|
||||
Intent.parseUri("${BuildConfig.DEEP_LINK_SCHEME}://open?url=$uri", 0)
|
||||
if (intent.action == Intent.ACTION_VIEW) {
|
||||
intent.addCategory(Intent.CATEGORY_BROWSABLE)
|
||||
intent.component = null
|
||||
intent.selector = null
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
}
|
||||
activity.startActivity(intent)
|
||||
},
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
hideToolbarFeature.set(
|
||||
feature = WebAppHideToolbarFeature(
|
||||
store = requireComponents.core.store,
|
||||
customTabsStore = requireComponents.core.customTabsStore,
|
||||
tabId = customTabSessionId,
|
||||
manifest = manifest
|
||||
) { toolbarVisible ->
|
||||
browserToolbarView.view.isVisible = toolbarVisible
|
||||
webAppToolbarShouldBeVisible = toolbarVisible
|
||||
if (!toolbarVisible) {
|
||||
engineView.setDynamicToolbarMaxHeight(0)
|
||||
val browserEngine =
|
||||
swipeRefresh.layoutParams as CoordinatorLayout.LayoutParams
|
||||
browserEngine.bottomMargin = 0
|
||||
}
|
||||
},
|
||||
owner = this,
|
||||
view = toolbar
|
||||
)
|
||||
|
||||
if (manifest != null) {
|
||||
activity.lifecycle.addObservers(
|
||||
WebAppActivityFeature(
|
||||
activity,
|
||||
components.core.icons,
|
||||
manifest
|
||||
),
|
||||
ManifestUpdateFeature(
|
||||
activity.applicationContext,
|
||||
requireComponents.core.store,
|
||||
requireComponents.core.webAppShortcutManager,
|
||||
requireComponents.core.webAppManifestStorage,
|
||||
customTabSessionId,
|
||||
manifest
|
||||
)
|
||||
)
|
||||
viewLifecycleOwner.lifecycle.addObserver(
|
||||
WebAppSiteControlsFeature(
|
||||
activity.applicationContext,
|
||||
requireComponents.core.store,
|
||||
requireComponents.useCases.sessionUseCases.reload,
|
||||
customTabSessionId,
|
||||
manifest,
|
||||
WebAppSiteControlsBuilder(
|
||||
requireComponents.core.sessionManager,
|
||||
requireComponents.useCases.sessionUseCases.reload,
|
||||
customTabSessionId,
|
||||
manifest
|
||||
)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
viewLifecycleOwner.lifecycle.addObserver(
|
||||
PoweredByNotification(
|
||||
activity.applicationContext,
|
||||
requireComponents.core.store,
|
||||
customTabSessionId
|
||||
)
|
||||
)
|
||||
windowFeature.set(
|
||||
feature = CustomTabWindowFeature(
|
||||
activity,
|
||||
components.core.store,
|
||||
customTabSessionId
|
||||
) { uri ->
|
||||
val intent =
|
||||
Intent.parseUri("${BuildConfig.DEEP_LINK_SCHEME}://open?url=$uri", 0)
|
||||
if (intent.action == Intent.ACTION_VIEW) {
|
||||
intent.addCategory(Intent.CATEGORY_BROWSABLE)
|
||||
intent.component = null
|
||||
intent.selector = null
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
}
|
||||
}
|
||||
activity.startActivity(intent)
|
||||
},
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
hideToolbarFeature.set(
|
||||
feature = WebAppHideToolbarFeature(
|
||||
store = requireComponents.core.store,
|
||||
customTabsStore = requireComponents.core.customTabsStore,
|
||||
tabId = customTabSessionId,
|
||||
manifest = manifest
|
||||
) { toolbarVisible ->
|
||||
browserToolbarView.view.isVisible = toolbarVisible
|
||||
webAppToolbarShouldBeVisible = toolbarVisible
|
||||
if (!toolbarVisible) {
|
||||
engineView.setDynamicToolbarMaxHeight(0)
|
||||
val browserEngine =
|
||||
swipeRefresh.layoutParams as CoordinatorLayout.LayoutParams
|
||||
browserEngine.bottomMargin = 0
|
||||
}
|
||||
},
|
||||
owner = this,
|
||||
view = toolbar
|
||||
)
|
||||
|
||||
if (manifest != null) {
|
||||
activity.lifecycle.addObservers(
|
||||
WebAppActivityFeature(
|
||||
activity,
|
||||
components.core.icons,
|
||||
manifest
|
||||
),
|
||||
ManifestUpdateFeature(
|
||||
activity.applicationContext,
|
||||
requireComponents.core.store,
|
||||
requireComponents.core.webAppShortcutManager,
|
||||
requireComponents.core.webAppManifestStorage,
|
||||
customTabSessionId,
|
||||
manifest
|
||||
)
|
||||
)
|
||||
viewLifecycleOwner.lifecycle.addObserver(
|
||||
WebAppSiteControlsFeature(
|
||||
activity.applicationContext,
|
||||
requireComponents.core.store,
|
||||
requireComponents.useCases.sessionUseCases.reload,
|
||||
customTabSessionId,
|
||||
manifest,
|
||||
WebAppSiteControlsBuilder(
|
||||
requireComponents.core.sessionManager,
|
||||
requireComponents.useCases.sessionUseCases.reload,
|
||||
customTabSessionId,
|
||||
manifest
|
||||
)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
viewLifecycleOwner.lifecycle.addObserver(
|
||||
PoweredByNotification(
|
||||
activity.applicationContext,
|
||||
requireComponents.core.store,
|
||||
customTabSessionId
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -197,14 +192,14 @@ class ExternalAppBrowserFragment : BaseBrowserFragment(), UserInteractionHandler
|
|||
nav(R.id.externalAppBrowserFragment, directions)
|
||||
}
|
||||
|
||||
override fun navToTrackingProtectionPanel(session: Session) {
|
||||
requireComponents.useCases.trackingProtectionUseCases.containsException(session.id) { contains ->
|
||||
val isEnabled = session.trackerBlockingEnabled && !contains
|
||||
override fun navToTrackingProtectionPanel(tab: SessionState) {
|
||||
requireComponents.useCases.trackingProtectionUseCases.containsException(tab.id) { contains ->
|
||||
val isEnabled = tab.trackingProtection.enabled && !contains
|
||||
val directions =
|
||||
ExternalAppBrowserFragmentDirections
|
||||
.actionGlobalTrackingProtectionPanelDialogFragment(
|
||||
sessionId = session.id,
|
||||
url = session.url,
|
||||
sessionId = tab.id,
|
||||
url = tab.content.url,
|
||||
trackingProtectionEnabled = isEnabled,
|
||||
gravity = getAppropriateLayoutGravity()
|
||||
)
|
||||
|
|
|
@ -87,13 +87,13 @@ class BrowserFragmentTest {
|
|||
every { browserFragment.onboarding } returns onboarding
|
||||
|
||||
every { browserFragment.requireContext() } returns context
|
||||
every { browserFragment.initializeUI(any()) } returns mockk()
|
||||
every { browserFragment.initializeUI(any(), any()) } returns mockk()
|
||||
every { browserFragment.fullScreenChanged(any()) } returns Unit
|
||||
every { browserFragment.resumeDownloadDialogState(any(), any(), any(), any(), any()) } returns Unit
|
||||
|
||||
testTab = createTab(url = "https://mozilla.org")
|
||||
store = BrowserStore()
|
||||
every { context.components.core.store } returns store
|
||||
testTab = createTab(url = "https://mozilla.org")
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -122,10 +122,10 @@ class BrowserFragmentTest {
|
|||
@Test
|
||||
fun `GIVEN browser UI is not initialized WHEN selected tab changes THEN browser UI is initialized`() {
|
||||
browserFragment.observeTabSelection(store)
|
||||
verify(exactly = 0) { browserFragment.initializeUI(view) }
|
||||
verify(exactly = 0) { browserFragment.initializeUI(view, testTab) }
|
||||
|
||||
addAndSelectTab(testTab)
|
||||
verify(exactly = 1) { browserFragment.initializeUI(view) }
|
||||
verify(exactly = 1) { browserFragment.initializeUI(view, testTab) }
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue