tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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:
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/search/BrowserToolbarSearchMiddleware.kt | 2+-
Mmobile/android/fenix/app/src/test/java/org/mozilla/fenix/search/BrowserToolbarSearchMiddlewareTest.kt | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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)