For #5843 - Ensure tabs pending deletion are removed
parent
13c9c39658
commit
7f34204188
|
@ -5,6 +5,7 @@
|
|||
package org.mozilla.fenix.components
|
||||
|
||||
import GeckoProvider
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import io.sentry.Sentry
|
||||
|
@ -116,6 +117,11 @@ class Core(private val context: Context) {
|
|||
*/
|
||||
val customTabsStore by lazy { CustomTabsServiceStore() }
|
||||
|
||||
/**
|
||||
* The [PendingSessionDeletionManager] maintains a set of sessionIds that are marked for deletion
|
||||
*/
|
||||
val pendingSessionDeletionManager by lazy { PendingSessionDeletionManager(context as Application) }
|
||||
|
||||
/**
|
||||
* The session manager component provides access to a centralized registry of
|
||||
* all browser sessions (i.e. tabs). It is initialized here to persist and restore
|
||||
|
@ -142,6 +148,12 @@ class Core(private val context: Context) {
|
|||
)
|
||||
}
|
||||
|
||||
pendingSessionDeletionManager.getSessionsToDelete(context).forEach {
|
||||
sessionManager.findSessionById(it)?.let { session ->
|
||||
sessionManager.remove(session)
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we have restored our previous state (if there's one) let's setup auto saving the state while
|
||||
// the app is used.
|
||||
sessionStorage.autoSave(sessionManager)
|
||||
|
@ -277,13 +289,13 @@ class Core(private val context: Context) {
|
|||
}
|
||||
|
||||
private fun geCustomCookiePolicy(): CookiePolicy {
|
||||
return when (context.settings().blockCookiesSelectionInCustomTrackingProtection) {
|
||||
"all" -> CookiePolicy.ACCEPT_NONE
|
||||
"social" -> CookiePolicy.ACCEPT_NON_TRACKERS
|
||||
"unvisited" -> CookiePolicy.ACCEPT_VISITED
|
||||
"third-party" -> CookiePolicy.ACCEPT_ONLY_FIRST_PARTY
|
||||
else -> CookiePolicy.ACCEPT_NONE
|
||||
}
|
||||
return when (context.settings().blockCookiesSelectionInCustomTrackingProtection) {
|
||||
"all" -> CookiePolicy.ACCEPT_NONE
|
||||
"social" -> CookiePolicy.ACCEPT_NON_TRACKERS
|
||||
"unvisited" -> CookiePolicy.ACCEPT_VISITED
|
||||
"third-party" -> CookiePolicy.ACCEPT_ONLY_FIRST_PARTY
|
||||
else -> CookiePolicy.ACCEPT_NONE
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCustomTrackingCategories(): Array<TrackingCategory> {
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/* 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.components
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import org.mozilla.fenix.ext.settings
|
||||
|
||||
class PendingSessionDeletionManager(application: Application) :
|
||||
Application.ActivityLifecycleCallbacks {
|
||||
|
||||
private val sessionIdsPendingDeletion = mutableSetOf<String>()
|
||||
|
||||
init {
|
||||
application.registerActivityLifecycleCallbacks(this)
|
||||
}
|
||||
|
||||
fun addSession(sessionId: String) {
|
||||
sessionIdsPendingDeletion.add(sessionId)
|
||||
}
|
||||
|
||||
fun removeSession(sessionId: String) {
|
||||
sessionIdsPendingDeletion.remove(sessionId)
|
||||
}
|
||||
|
||||
fun getSessionsToDelete(context: Context): Set<String> {
|
||||
return context.settings().preferences.getStringSet(
|
||||
PREF_KEY,
|
||||
setOf()
|
||||
) ?: setOf()
|
||||
}
|
||||
|
||||
override fun onActivityPaused(activity: Activity?) {
|
||||
activity?.settings()?.preferences?.edit()?.putStringSet(
|
||||
PREF_KEY,
|
||||
sessionIdsPendingDeletion
|
||||
)?.apply()
|
||||
}
|
||||
|
||||
override fun onActivityResumed(p0: Activity?) {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
override fun onActivityStarted(p0: Activity?) {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
override fun onActivityDestroyed(p0: Activity?) {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
override fun onActivitySaveInstanceState(p0: Activity?, p1: Bundle?) {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
override fun onActivityStopped(p0: Activity?) {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
override fun onActivityCreated(p0: Activity?, p1: Bundle?) {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val PREF_KEY = "pref_key_session_id_set_to_delete"
|
||||
}
|
||||
}
|
|
@ -202,7 +202,7 @@ class HomeFragment : Fragment() {
|
|||
registerCollectionStorageObserver = ::registerCollectionStorageObserver,
|
||||
scrollToTheTop = ::scrollToTheTop,
|
||||
showDeleteCollectionPrompt = ::showDeleteCollectionPrompt,
|
||||
openSettingsScreen = :: openSettingsScreen
|
||||
openSettingsScreen = ::openSettingsScreen
|
||||
)
|
||||
)
|
||||
updateLayout(view)
|
||||
|
@ -277,7 +277,8 @@ class HomeFragment : Fragment() {
|
|||
// TODO remove when viewLifecycleOwner is fixed
|
||||
val context = context ?: return@launch
|
||||
|
||||
val iconSize = context.resources.getDimensionPixelSize(R.dimen.preference_icon_drawable_size)
|
||||
val iconSize =
|
||||
context.resources.getDimensionPixelSize(R.dimen.preference_icon_drawable_size)
|
||||
|
||||
val searchEngine = context.components.search.provider.getDefaultEngine(context)
|
||||
val searchIcon = BitmapDrawable(context.resources, searchEngine.icon)
|
||||
|
@ -336,7 +337,8 @@ class HomeFragment : Fragment() {
|
|||
|
||||
if (onboarding.userHasBeenOnboarded()) {
|
||||
homeFragmentStore.dispatch(
|
||||
HomeFragmentAction.ModeChange(Mode.fromBrowsingMode(newMode)))
|
||||
HomeFragmentAction.ModeChange(Mode.fromBrowsingMode(newMode))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -355,12 +357,14 @@ class HomeFragment : Fragment() {
|
|||
val context = requireContext()
|
||||
val components = context.components
|
||||
|
||||
homeFragmentStore.dispatch(HomeFragmentAction.Change(
|
||||
collections = components.core.tabCollectionStorage.cachedTabCollections,
|
||||
mode = currentMode.getCurrentMode(),
|
||||
tabs = getListOfSessions().toTabs(),
|
||||
topSites = components.core.topSiteStorage.cachedTopSites
|
||||
))
|
||||
homeFragmentStore.dispatch(
|
||||
HomeFragmentAction.Change(
|
||||
collections = components.core.tabCollectionStorage.cachedTabCollections,
|
||||
mode = currentMode.getCurrentMode(),
|
||||
tabs = getListOfSessions().toTabs(),
|
||||
topSites = components.core.topSiteStorage.cachedTopSites
|
||||
)
|
||||
)
|
||||
|
||||
requireComponents.backgroundServices.accountManager.register(currentMode, owner = this)
|
||||
requireComponents.backgroundServices.accountManager.register(object : AccountObserver {
|
||||
|
@ -377,7 +381,8 @@ class HomeFragment : Fragment() {
|
|||
}, owner = this)
|
||||
|
||||
if (context.settings().showPrivateModeContextualFeatureRecommender &&
|
||||
browsingModeManager.mode.isPrivate) {
|
||||
browsingModeManager.mode.isPrivate
|
||||
) {
|
||||
recommendPrivateBrowsingShortcut()
|
||||
}
|
||||
|
||||
|
@ -517,7 +522,8 @@ class HomeFragment : Fragment() {
|
|||
// Otherwise, we will encounter an activity token error.
|
||||
privateBrowsingButton.post {
|
||||
privateBrowsingRecommend.showAsDropDown(
|
||||
privateBrowsingButton, 0, CFR_Y_OFFSET, Gravity.TOP or Gravity.END)
|
||||
privateBrowsingButton, 0, CFR_Y_OFFSET, Gravity.TOP or Gravity.END
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -528,7 +534,9 @@ class HomeFragment : Fragment() {
|
|||
homeFragmentStore.dispatch(
|
||||
HomeFragmentAction.ModeChange(
|
||||
mode = currentMode.getCurrentMode(),
|
||||
tabs = getListOfSessions().toTabs()))
|
||||
tabs = getListOfSessions().toTabs()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -633,10 +641,16 @@ class HomeFragment : Fragment() {
|
|||
|
||||
private fun removeAllTabsWithUndo(listOfSessionsToDelete: Sequence<Session>, private: Boolean) {
|
||||
homeFragmentStore.dispatch(HomeFragmentAction.TabsChange(emptyList()))
|
||||
listOfSessionsToDelete.forEach {
|
||||
requireComponents.core.pendingSessionDeletionManager.addSession(
|
||||
it.id
|
||||
)
|
||||
}
|
||||
|
||||
val deleteOperation: (suspend () -> Unit) = {
|
||||
listOfSessionsToDelete.forEach {
|
||||
sessionManager.remove(it)
|
||||
requireComponents.core.pendingSessionDeletionManager.removeSession(it.id)
|
||||
}
|
||||
}
|
||||
deleteAllSessionsJob = deleteOperation
|
||||
|
@ -651,6 +665,11 @@ class HomeFragment : Fragment() {
|
|||
view!!,
|
||||
snackbarMessage,
|
||||
getString(R.string.snackbar_deleted_undo), {
|
||||
listOfSessionsToDelete.forEach {
|
||||
requireComponents.core.pendingSessionDeletionManager.removeSession(
|
||||
it.id
|
||||
)
|
||||
}
|
||||
if (private) {
|
||||
requireComponents.analytics.metrics.track(Event.PrivateBrowsingSnackbarUndoTapped)
|
||||
}
|
||||
|
@ -664,11 +683,13 @@ class HomeFragment : Fragment() {
|
|||
|
||||
private fun removeTabWithUndo(sessionId: String, private: Boolean) {
|
||||
val sessionManager = requireComponents.core.sessionManager
|
||||
requireComponents.core.pendingSessionDeletionManager.addSession(sessionId)
|
||||
val deleteOperation: (suspend () -> Unit) = {
|
||||
sessionManager.findSessionById(sessionId)
|
||||
?.let { session ->
|
||||
pendingSessionDeletion = null
|
||||
sessionManager.remove(session)
|
||||
requireComponents.core.pendingSessionDeletionManager.removeSession(sessionId)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -684,6 +705,7 @@ class HomeFragment : Fragment() {
|
|||
view!!,
|
||||
snackbarMessage,
|
||||
getString(R.string.snackbar_deleted_undo), {
|
||||
requireComponents.core.pendingSessionDeletionManager.removeSession(sessionId)
|
||||
pendingSessionDeletion = null
|
||||
emitSessionChanges()
|
||||
},
|
||||
|
@ -777,8 +799,12 @@ class HomeFragment : Fragment() {
|
|||
border?.visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onAnimationStart(animation: Animator?) { /* noop */ }
|
||||
override fun onAnimationRepeat(animation: Animator?) { /* noop */ }
|
||||
override fun onAnimationStart(animation: Animator?) { /* noop */
|
||||
}
|
||||
|
||||
override fun onAnimationRepeat(animation: Animator?) { /* noop */
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
border?.animate()?.alpha(0.0F)?.setStartDelay(ANIM_ON_SCREEN_DELAY)
|
||||
?.setDuration(FADE_ANIM_DURATION)
|
||||
|
|
Loading…
Reference in New Issue