Bug 1872704 - Fix home activity leak by ExtensionsProcessDisabledController
parent
ccefb2dd2d
commit
04d83965a4
@ -0,0 +1,49 @@
|
|||||||
|
/* 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.addons
|
||||||
|
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import mozilla.components.browser.state.store.BrowserStore
|
||||||
|
import mozilla.components.support.webextensions.ExtensionsProcessDisabledPromptObserver
|
||||||
|
import org.mozilla.fenix.components.AppStore
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller for handling extensions process spawning disabled events. This is for when the app is
|
||||||
|
* in background, the app is killed to prevent extensions from being disabled and network requests
|
||||||
|
* continuing.
|
||||||
|
*
|
||||||
|
* @param browserStore The [BrowserStore] which holds the state for showing the dialog.
|
||||||
|
* @param appStore The [AppStore] containing the application state.
|
||||||
|
* @param onExtensionsProcessDisabled Invoked when the app is in background and extensions process
|
||||||
|
* is disabled.
|
||||||
|
*/
|
||||||
|
class ExtensionsProcessDisabledBackgroundController(
|
||||||
|
browserStore: BrowserStore,
|
||||||
|
appStore: AppStore,
|
||||||
|
onExtensionsProcessDisabled: () -> Unit = { killApp() },
|
||||||
|
) : ExtensionsProcessDisabledPromptObserver(
|
||||||
|
store = browserStore,
|
||||||
|
shouldCancelOnStop = false,
|
||||||
|
onShowExtensionsProcessDisabledPrompt = {
|
||||||
|
if (!appStore.state.isForeground) {
|
||||||
|
onExtensionsProcessDisabled()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* When a dialog can't be shown because the app is in the background, instead the app will
|
||||||
|
* be killed to prevent leaking network data without extensions enabled.
|
||||||
|
*/
|
||||||
|
private fun killApp() {
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
exitProcess(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
/* 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.addons
|
||||||
|
|
||||||
|
import mozilla.components.browser.state.action.ExtensionsProcessAction
|
||||||
|
import mozilla.components.browser.state.state.BrowserState
|
||||||
|
import mozilla.components.browser.state.store.BrowserStore
|
||||||
|
import mozilla.components.support.test.libstate.ext.waitUntilIdle
|
||||||
|
import mozilla.components.support.test.rule.MainCoroutineRule
|
||||||
|
import org.junit.Assert.assertFalse
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.mozilla.fenix.components.AppStore
|
||||||
|
import org.mozilla.fenix.components.appstate.AppState
|
||||||
|
|
||||||
|
class ExtensionsProcessDisabledBackgroundControllerTest {
|
||||||
|
|
||||||
|
@get:Rule
|
||||||
|
val coroutinesTestRule = MainCoroutineRule()
|
||||||
|
private val dispatcher = coroutinesTestRule.testDispatcher
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `WHEN app is backgrounded AND extension process spawning threshold is exceeded THEN onExtensionsProcessDisabled is invoked`() {
|
||||||
|
val browserStore = BrowserStore(BrowserState())
|
||||||
|
val appStore = AppStore(AppState(isForeground = false))
|
||||||
|
var invoked = false
|
||||||
|
|
||||||
|
val controller = ExtensionsProcessDisabledBackgroundController(
|
||||||
|
browserStore,
|
||||||
|
appStore,
|
||||||
|
onExtensionsProcessDisabled = {
|
||||||
|
invoked = true
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
controller.start()
|
||||||
|
|
||||||
|
browserStore.dispatch(ExtensionsProcessAction.ShowPromptAction(show = true))
|
||||||
|
dispatcher.scheduler.advanceUntilIdle()
|
||||||
|
browserStore.waitUntilIdle()
|
||||||
|
|
||||||
|
assertTrue(invoked)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `WHEN app is in foreground AND extension process spawning threshold is exceeded THEN onExtensionsProcessDisabled is not invoked`() {
|
||||||
|
val browserStore = BrowserStore(BrowserState())
|
||||||
|
val appStore = AppStore(AppState(isForeground = true))
|
||||||
|
var invoked = false
|
||||||
|
|
||||||
|
val controller = ExtensionsProcessDisabledBackgroundController(
|
||||||
|
browserStore,
|
||||||
|
appStore,
|
||||||
|
onExtensionsProcessDisabled = {
|
||||||
|
invoked = true
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
controller.start()
|
||||||
|
|
||||||
|
browserStore.dispatch(ExtensionsProcessAction.ShowPromptAction(show = true))
|
||||||
|
dispatcher.scheduler.advanceUntilIdle()
|
||||||
|
browserStore.waitUntilIdle()
|
||||||
|
|
||||||
|
assertFalse(invoked)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue