commit 6cda0cf79bbd7f97df2695904070a33e26fd5962
parent 9e78e273bf8c1a71fece48f072120cf3a3d0a847
Author: Mugurell <Mugurell@users.noreply.github.com>
Date: Mon, 6 Oct 2025 17:43:25 +0000
Bug 1988357 - part 1 - If QR code was scanned while in private then open URL in private r=android-reviewers,Roger
Differential Revision: https://phabricator.services.mozilla.com/D267569
Diffstat:
2 files changed, 109 insertions(+), 1 deletion(-)
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/search/BrowserToolbarSearchMiddleware.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/search/BrowserToolbarSearchMiddleware.kt
@@ -522,7 +522,7 @@ class BrowserToolbarSearchMiddleware(
searchTermOrURL = it.qrScannerState.lastScanData,
newTab = appStore.state.searchState.sourceTabId == null,
flags = EngineSession.LoadUrlFlags.external(),
- private = false,
+ private = environment?.browsingModeManager?.mode == Private,
)
environment?.navController?.navigate(
resId = R.id.browserFragment,
diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/search/BrowserToolbarSearchMiddlewareTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/search/BrowserToolbarSearchMiddlewareTest.kt
@@ -35,6 +35,7 @@ import mozilla.components.compose.browser.toolbar.store.BrowserToolbarInteractio
import mozilla.components.compose.browser.toolbar.store.BrowserToolbarStore
import mozilla.components.compose.browser.toolbar.store.EnvironmentCleared
import mozilla.components.compose.browser.toolbar.store.EnvironmentRehydrated
+import mozilla.components.concept.engine.EngineSession
import mozilla.components.concept.toolbar.AutocompleteProvider
import mozilla.components.support.test.ext.joinBlocking
import mozilla.components.support.test.middleware.CaptureActionsMiddleware
@@ -56,10 +57,13 @@ import org.mozilla.fenix.NavGraphDirections
import org.mozilla.fenix.R
import org.mozilla.fenix.browser.BrowserFragmentDirections
import org.mozilla.fenix.browser.browsingmode.BrowsingMode.Normal
+import org.mozilla.fenix.browser.browsingmode.BrowsingMode.Private
import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager
import org.mozilla.fenix.components.AppStore
import org.mozilla.fenix.components.Components
import org.mozilla.fenix.components.appstate.AppAction
+import org.mozilla.fenix.components.appstate.AppAction.QrScannerAction.QrScannerInputAvailable
+import org.mozilla.fenix.components.appstate.AppAction.QrScannerAction.QrScannerInputConsumed
import org.mozilla.fenix.components.appstate.AppAction.QrScannerAction.QrScannerRequested
import org.mozilla.fenix.components.appstate.AppAction.SearchAction.SearchEnded
import org.mozilla.fenix.components.appstate.AppAction.SearchAction.SearchStarted
@@ -815,6 +819,110 @@ class BrowserToolbarSearchMiddlewareTest {
}
@Test
+ fun `GIVEN QR scan while in normal browsing mode WHEN receiving a result THEN open it as a new normal tab`() {
+ val appStoreActionsCaptor = CaptureActionsMiddleware<AppState, AppAction>()
+ val appStore = AppStore(middlewares = listOf(appStoreActionsCaptor))
+ val browserUseCases: FenixBrowserUseCases = mockk(relaxed = true)
+ every { components.useCases.fenixBrowserUseCases } returns browserUseCases
+ val browsingModeManager: BrowsingModeManager = mockk(relaxed = true) {
+ every { mode } returns Normal
+ }
+ val (_, store) = buildMiddlewareAndAddToStore(
+ appStore = appStore,
+ components = components,
+ browsingModeManager = browsingModeManager,
+ )
+ store.dispatch(ToggleEditMode(true))
+ val qrScannerButton = store.state.editState.editActionsEnd.last() as ActionButtonRes
+
+ store.dispatch(qrScannerButton.onClick as BrowserToolbarEvent).joinBlocking()
+ appStore.dispatch(QrScannerInputAvailable("mozilla.test")).joinBlocking()
+ shadowOf(Looper.getMainLooper()).idle() // wait for observing and processing qr scan result
+
+ assertEquals("mozilla.test", store.state.editState.query)
+ appStoreActionsCaptor.assertLastAction(QrScannerInputConsumed::class)
+ verify {
+ browserUseCases.loadUrlOrSearch(
+ searchTermOrURL = "mozilla.test",
+ newTab = true,
+ flags = EngineSession.LoadUrlFlags.external(),
+ private = false,
+ )
+ }
+ }
+
+ @Test
+ fun `GIVEN QR scan while in private browsing mode WHEN receiving a result THEN open it as a new private tab`() {
+ val appStoreActionsCaptor = CaptureActionsMiddleware<AppState, AppAction>()
+ val appStore = AppStore(middlewares = listOf(appStoreActionsCaptor))
+ val browserUseCases: FenixBrowserUseCases = mockk(relaxed = true)
+ every { components.useCases.fenixBrowserUseCases } returns browserUseCases
+ val browsingModeManager: BrowsingModeManager = mockk(relaxed = true) {
+ every { mode } returns Private
+ }
+ val (_, store) = buildMiddlewareAndAddToStore(
+ appStore = appStore,
+ components = components,
+ browsingModeManager = browsingModeManager,
+ )
+ store.dispatch(ToggleEditMode(true))
+ val qrScannerButton = store.state.editState.editActionsEnd.last() as ActionButtonRes
+
+ store.dispatch(qrScannerButton.onClick as BrowserToolbarEvent).joinBlocking()
+ appStore.dispatch(QrScannerInputAvailable("test.mozilla")).joinBlocking()
+ shadowOf(Looper.getMainLooper()).idle() // wait for observing and processing qr scan result
+
+ assertEquals("test.mozilla", store.state.editState.query)
+ appStoreActionsCaptor.assertLastAction(QrScannerInputConsumed::class)
+ verify {
+ browserUseCases.loadUrlOrSearch(
+ searchTermOrURL = "test.mozilla",
+ newTab = true,
+ flags = EngineSession.LoadUrlFlags.external(),
+ private = true,
+ )
+ }
+ }
+
+ @Test
+ fun `GIVEN QR scan starteds from browser WHEN receiving a result THEN open it in the same tab`() {
+ val appStoreActionsCaptor = CaptureActionsMiddleware<AppState, AppAction>()
+ val appStore = AppStore(
+ initialState = AppState(
+ searchState = AppSearchState.EMPTY.copy(sourceTabId = "test"),
+ ),
+ middlewares = listOf(appStoreActionsCaptor),
+ )
+ val browserUseCases: FenixBrowserUseCases = mockk(relaxed = true)
+ every { components.useCases.fenixBrowserUseCases } returns browserUseCases
+ val browsingModeManager: BrowsingModeManager = mockk(relaxed = true) {
+ every { mode } returns Normal
+ }
+ val (_, store) = buildMiddlewareAndAddToStore(
+ appStore = appStore,
+ components = components,
+ browsingModeManager = browsingModeManager,
+ )
+ store.dispatch(ToggleEditMode(true))
+ val qrScannerButton = store.state.editState.editActionsEnd.last() as ActionButtonRes
+
+ store.dispatch(qrScannerButton.onClick as BrowserToolbarEvent).joinBlocking()
+ appStore.dispatch(QrScannerInputAvailable("test.com")).joinBlocking()
+ shadowOf(Looper.getMainLooper()).idle() // wait for observing and processing qr scan result
+
+ assertEquals("test.com", store.state.editState.query)
+ appStoreActionsCaptor.assertLastAction(QrScannerInputConsumed::class)
+ verify {
+ browserUseCases.loadUrlOrSearch(
+ searchTermOrURL = "test.com",
+ newTab = false,
+ flags = EngineSession.LoadUrlFlags.external(),
+ private = false,
+ )
+ }
+ }
+
+ @Test
fun `WHEN the voice action is tapped THEN add a new voice input request to the AppStore`() {
val appStore: AppStore = mockk(relaxed = true) {
every { state } returns mockk(relaxed = true)