Fix #1032: Crash altering sessions DB on main thread
parent
9255962219
commit
6e1655e935
|
@ -0,0 +1,23 @@
|
||||||
|
/* 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.ext
|
||||||
|
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import mozilla.components.browser.session.SessionManager
|
||||||
|
import mozilla.components.feature.session.bundling.SessionBundleStorage
|
||||||
|
|
||||||
|
suspend fun SessionBundleStorage.archive(sessionManager: SessionManager) {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
save(sessionManager.createSnapshot())
|
||||||
|
launch(Dispatchers.Main) {
|
||||||
|
sessionManager.sessions.filter { !it.private }.forEach {
|
||||||
|
sessionManager.remove(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new()
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,15 +21,20 @@ import androidx.lifecycle.Observer
|
||||||
import androidx.navigation.Navigation
|
import androidx.navigation.Navigation
|
||||||
import kotlinx.android.synthetic.main.fragment_home.*
|
import kotlinx.android.synthetic.main.fragment_home.*
|
||||||
import kotlinx.android.synthetic.main.fragment_home.view.*
|
import kotlinx.android.synthetic.main.fragment_home.view.*
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import mozilla.components.browser.menu.BrowserMenu
|
import mozilla.components.browser.menu.BrowserMenu
|
||||||
import mozilla.components.browser.session.Session
|
import mozilla.components.browser.session.Session
|
||||||
import mozilla.components.browser.session.SessionManager
|
import mozilla.components.browser.session.SessionManager
|
||||||
import mozilla.components.feature.session.bundling.SessionBundleStorage
|
import org.mozilla.fenix.BrowserDirection
|
||||||
import org.mozilla.fenix.BrowsingModeManager
|
import org.mozilla.fenix.BrowsingModeManager
|
||||||
import org.mozilla.fenix.DefaultThemeManager
|
import org.mozilla.fenix.DefaultThemeManager
|
||||||
import org.mozilla.fenix.HomeActivity
|
import org.mozilla.fenix.HomeActivity
|
||||||
import org.mozilla.fenix.BrowserDirection
|
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
|
import org.mozilla.fenix.ext.archive
|
||||||
import org.mozilla.fenix.ext.requireComponents
|
import org.mozilla.fenix.ext.requireComponents
|
||||||
import org.mozilla.fenix.home.sessions.ArchivedSession
|
import org.mozilla.fenix.home.sessions.ArchivedSession
|
||||||
import org.mozilla.fenix.home.sessions.SessionsAction
|
import org.mozilla.fenix.home.sessions.SessionsAction
|
||||||
|
@ -44,30 +49,27 @@ import org.mozilla.fenix.mvi.ActionBusFactory
|
||||||
import org.mozilla.fenix.mvi.getAutoDisposeObservable
|
import org.mozilla.fenix.mvi.getAutoDisposeObservable
|
||||||
import org.mozilla.fenix.mvi.getManagedEmitter
|
import org.mozilla.fenix.mvi.getManagedEmitter
|
||||||
import org.mozilla.fenix.settings.SupportUtils
|
import org.mozilla.fenix.settings.SupportUtils
|
||||||
import org.mozilla.fenix.utils.Settings
|
import kotlin.coroutines.CoroutineContext
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
fun SessionBundleStorage.archive(sessionManager: SessionManager) {
|
|
||||||
save(sessionManager.createSnapshot())
|
|
||||||
sessionManager.sessions.filter { !it.private }.forEach {
|
|
||||||
sessionManager.remove(it)
|
|
||||||
}
|
|
||||||
new()
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("TooManyFunctions")
|
@SuppressWarnings("TooManyFunctions")
|
||||||
class HomeFragment : Fragment() {
|
class HomeFragment : Fragment(), CoroutineScope {
|
||||||
private val bus = ActionBusFactory.get(this)
|
private val bus = ActionBusFactory.get(this)
|
||||||
private var sessionObserver: SessionManager.Observer? = null
|
private var sessionObserver: SessionManager.Observer? = null
|
||||||
private var homeMenu: HomeMenu? = null
|
private var homeMenu: HomeMenu? = null
|
||||||
private lateinit var tabsComponent: TabsComponent
|
private lateinit var tabsComponent: TabsComponent
|
||||||
private lateinit var sessionsComponent: SessionsComponent
|
private lateinit var sessionsComponent: SessionsComponent
|
||||||
|
|
||||||
|
private lateinit var job: Job
|
||||||
|
override val coroutineContext: CoroutineContext
|
||||||
|
get() = Dispatchers.Main + job
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? {
|
): View? {
|
||||||
|
job = Job()
|
||||||
val view = inflater.inflate(R.layout.fragment_home, container, false)
|
val view = inflater.inflate(R.layout.fragment_home, container, false)
|
||||||
val sessionManager = requireComponents.core.sessionManager
|
val sessionManager = requireComponents.core.sessionManager
|
||||||
tabsComponent = TabsComponent(
|
tabsComponent = TabsComponent(
|
||||||
|
@ -174,8 +176,9 @@ class HomeFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
|
||||||
homeMenu = null
|
homeMenu = null
|
||||||
|
job.cancel()
|
||||||
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
|
@ -191,7 +194,9 @@ class HomeFragment : Fragment() {
|
||||||
.subscribe {
|
.subscribe {
|
||||||
when (it) {
|
when (it) {
|
||||||
is TabsAction.Archive -> {
|
is TabsAction.Archive -> {
|
||||||
requireComponents.core.sessionStorage.archive(requireComponents.core.sessionManager)
|
launch {
|
||||||
|
requireComponents.core.sessionStorage.archive(requireComponents.core.sessionManager)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
is TabsAction.MenuTapped -> {
|
is TabsAction.MenuTapped -> {
|
||||||
val isPrivate = (activity as HomeActivity).browsingModeManager.isPrivate
|
val isPrivate = (activity as HomeActivity).browsingModeManager.isPrivate
|
||||||
|
@ -228,14 +233,18 @@ class HomeFragment : Fragment() {
|
||||||
.subscribe {
|
.subscribe {
|
||||||
when (it) {
|
when (it) {
|
||||||
is SessionsAction.Select -> {
|
is SessionsAction.Select -> {
|
||||||
requireComponents.core.sessionStorage.archive(requireComponents.core.sessionManager)
|
launch {
|
||||||
|
requireComponents.core.sessionStorage.archive(requireComponents.core.sessionManager)
|
||||||
|
}
|
||||||
it.archivedSession.bundle.restoreSnapshot()?.apply {
|
it.archivedSession.bundle.restoreSnapshot()?.apply {
|
||||||
requireComponents.core.sessionManager.restore(this)
|
requireComponents.core.sessionManager.restore(this)
|
||||||
homeScrollView.smoothScrollTo(0, 0)
|
homeScrollView.smoothScrollTo(0, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is SessionsAction.Delete -> {
|
is SessionsAction.Delete -> {
|
||||||
requireComponents.core.sessionStorage.remove(it.archivedSession.bundle)
|
launch(IO) {
|
||||||
|
requireComponents.core.sessionStorage.remove(it.archivedSession.bundle)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
is SessionsAction.MenuTapped ->
|
is SessionsAction.MenuTapped ->
|
||||||
openSessionMenu(SessionBottomSheetFragment.SessionType.Archived(it.archivedSession))
|
openSessionMenu(SessionBottomSheetFragment.SessionType.Archived(it.archivedSession))
|
||||||
|
@ -358,17 +367,23 @@ class HomeFragment : Fragment() {
|
||||||
private fun openSessionMenu(sessionType: SessionBottomSheetFragment.SessionType) {
|
private fun openSessionMenu(sessionType: SessionBottomSheetFragment.SessionType) {
|
||||||
SessionBottomSheetFragment.create(sessionType).apply {
|
SessionBottomSheetFragment.create(sessionType).apply {
|
||||||
onArchive = {
|
onArchive = {
|
||||||
requireComponents.core.sessionStorage.archive(requireComponents.core.sessionManager)
|
launch {
|
||||||
|
requireComponents.core.sessionStorage.archive(requireComponents.core.sessionManager)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onDelete = {
|
onDelete = {
|
||||||
when (it) {
|
when (it) {
|
||||||
is SessionBottomSheetFragment.SessionType.Archived -> {
|
is SessionBottomSheetFragment.SessionType.Archived -> {
|
||||||
requireComponents.core.sessionStorage.remove(it.archivedSession.bundle)
|
launch(IO) {
|
||||||
|
requireComponents.core.sessionStorage.remove(it.archivedSession.bundle)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
is SessionBottomSheetFragment.SessionType.Current -> {
|
is SessionBottomSheetFragment.SessionType.Current -> {
|
||||||
requireComponents.useCases.tabsUseCases.removeAllTabsOfType.invoke(false)
|
requireComponents.useCases.tabsUseCases.removeAllTabsOfType.invoke(false)
|
||||||
requireComponents.core.sessionStorage.current()?.apply {
|
launch(IO) {
|
||||||
requireComponents.core.sessionStorage.remove(this)
|
requireComponents.core.sessionStorage.current()?.apply {
|
||||||
|
requireComponents.core.sessionStorage.remove(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is SessionBottomSheetFragment.SessionType.Private -> {
|
is SessionBottomSheetFragment.SessionType.Private -> {
|
||||||
|
|
|
@ -68,5 +68,5 @@ task ktlint(type: JavaExec, group: "verification") {
|
||||||
description = "Check Kotlin code style."
|
description = "Check Kotlin code style."
|
||||||
classpath = configurations.ktlint
|
classpath = configurations.ktlint
|
||||||
main = "com.github.shyiko.ktlint.Main"
|
main = "com.github.shyiko.ktlint.Main"
|
||||||
args "app/**/*.kt", "architecture/**/*.kt"
|
args "app/src/**/*.kt", "architecture/src/**/*.kt"
|
||||||
}
|
}
|
|
@ -46,7 +46,7 @@ object Deps {
|
||||||
const val tools_appservicesgradle = "org.mozilla.appservices:gradle-plugin:${Versions.appservices_gradle_plugin}"
|
const val tools_appservicesgradle = "org.mozilla.appservices:gradle-plugin:${Versions.appservices_gradle_plugin}"
|
||||||
const val kotlin_stdlib = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${Versions.kotlin}"
|
const val kotlin_stdlib = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${Versions.kotlin}"
|
||||||
|
|
||||||
const val allopen = "org.jetbrains.kotlin:kotlin-allopen:${Versions.kotlin}"
|
const val allopen = "org.jetbrains.kotlin:kotlin-allopen:${Versions.kotlin}"
|
||||||
|
|
||||||
const val rxKotlin = "io.reactivex.rxjava2:rxkotlin:${Versions.rxKotlin}"
|
const val rxKotlin = "io.reactivex.rxjava2:rxkotlin:${Versions.rxKotlin}"
|
||||||
const val rxAndroid = "io.reactivex.rxjava2:rxandroid:${Versions.rxAndroid}"
|
const val rxAndroid = "io.reactivex.rxjava2:rxandroid:${Versions.rxAndroid}"
|
||||||
|
@ -147,4 +147,3 @@ object Deps {
|
||||||
const val glide = "com.github.bumptech.glide:glide:${Versions.glide}"
|
const val glide = "com.github.bumptech.glide:glide:${Versions.glide}"
|
||||||
const val glideAnnotationProcessor = "com.github.bumptech.glide:compiler:${Versions.glide}"
|
const val glideAnnotationProcessor = "com.github.bumptech.glide:compiler:${Versions.glide}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue