Richard Pospesel pushed to branch tor-browser-102.2.1-12.0-2 at The Tor Project / Applications / fenix
Commits: 36285ece by Mugurell at 2023-04-11T20:38:05+00:00 Bug 1816059 - Show the notification for entering fullscreen as a Toast
- - - - - 216f33a3 by Alexandru2909 at 2023-04-11T20:46:41+00:00 Add FLAG_SECURE to SearchDialogFragment
- - - - -
3 changed files:
- app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt - app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt - + app/src/test/java/org/mozilla/fenix/search/SearchDialogFragmentTest.kt
Changes:
===================================== app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt ===================================== @@ -17,6 +17,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.view.accessibility.AccessibilityManager +import android.widget.Toast import androidx.annotation.CallSuper import androidx.annotation.VisibleForTesting import androidx.appcompat.app.AlertDialog @@ -1381,12 +1382,8 @@ abstract class BaseBrowserFragment : if (inFullScreen) { // Close find in page bar if opened findInPageIntegration.onBackPressed() - FenixSnackbar.make( - view = binding.dynamicSnackbarContainer, - duration = Snackbar.LENGTH_SHORT, - isDisplayedWithBrowserToolbar = false - ) - .setText(getString(R.string.full_screen_notification)) + Toast + .makeText(requireContext(), R.string.full_screen_notification, Toast.LENGTH_SHORT) .show() activity?.enterToImmersiveMode() browserToolbarView.collapse()
===================================== app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt ===================================== @@ -78,6 +78,7 @@ import org.mozilla.fenix.databinding.SearchSuggestionsHintBinding import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.increaseTapArea import org.mozilla.fenix.ext.requireComponents +import org.mozilla.fenix.ext.secure import org.mozilla.fenix.ext.settings import org.mozilla.fenix.search.awesomebar.AwesomeBarView import org.mozilla.fenix.search.awesomebar.toSearchProviderState @@ -151,6 +152,10 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { override fun onBackPressed() { this@SearchDialogFragment.onBackPressed() } + }.apply { + if ((requireActivity() as HomeActivity).browsingModeManager.mode.isPrivate) { + this.secure(requireActivity()) + } } }
===================================== app/src/test/java/org/mozilla/fenix/search/SearchDialogFragmentTest.kt ===================================== @@ -0,0 +1,212 @@ +/* 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.search + +import android.view.WindowManager.LayoutParams +import androidx.fragment.app.Fragment +import androidx.navigation.NavBackStackEntry +import androidx.navigation.NavController +import androidx.navigation.fragment.findNavController +import io.mockk.Called +import io.mockk.Runs +import io.mockk.every +import io.mockk.just +import io.mockk.mockk +import io.mockk.mockkStatic +import io.mockk.spyk +import io.mockk.unmockkStatic +import io.mockk.verify +import mozilla.components.browser.state.search.SearchEngine +import mozilla.components.browser.state.state.SearchState +import mozilla.components.browser.state.state.searchEngines +import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine +import mozilla.components.support.test.robolectric.testContext +import org.junit.After +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Assert.assertSame +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.HomeActivity +import org.mozilla.fenix.components.Components +import org.mozilla.fenix.ext.requireComponents +import org.mozilla.fenix.helpers.FenixRobolectricTestRunner + +@RunWith(FenixRobolectricTestRunner::class) +internal class SearchDialogFragmentTest { + private val navController: NavController = mockk() + private val fragment = SearchDialogFragment() + + @Before + fun setup() { + mockkStatic("androidx.navigation.fragment.FragmentKt") + every { any<Fragment>().findNavController() } returns navController + } + + @After + fun teardown() { + unmockkStatic("androidx.navigation.fragment.FragmentKt") + } + + @Test + fun `GIVEN this is the only visible fragment WHEN asking for the previous destination THEN return null`() { + every { navController.backQueue } returns ArrayDeque(listOf(getDestination(fragmentName))) + + assertNull(fragment.getPreviousDestination()) + } + + @Test + fun `GIVEN this and FragmentB on top of this are visible WHEN asking for the previous destination THEN return null`() { + every { navController.backQueue } returns ArrayDeque( + listOf( + getDestination(fragmentName), + getDestination("FragmentB"), + ), + ) + + assertNull(fragment.getPreviousDestination()) + } + + @Test + fun `GIVEN FragmentA, this and FragmentB are visible WHEN asking for the previous destination THEN return FragmentA`() { + val fragmentADestination = getDestination("FragmentA") + every { navController.backQueue } returns ArrayDeque( + listOf( + fragmentADestination, + getDestination(fragmentName), + getDestination("FragmentB"), + ), + ) + + assertSame(fragmentADestination, fragment.getPreviousDestination()) + } + + @Test + fun `GIVEN FragmentA and this on top of it are visible WHEN asking for the previous destination THEN return FragmentA`() { + val fragmentADestination = getDestination("FragmentA") + every { navController.backQueue } returns ArrayDeque( + listOf( + fragmentADestination, + getDestination(fragmentName), + ), + ) + + assertSame(fragmentADestination, fragment.getPreviousDestination()) + } + + @Test + fun `GIVEN the default search engine is currently selected WHEN checking the need to update the current search engine THEN don't to anything`() { + fragment.interactor = mockk() + val defaultSearchEngine: SearchEngine = mockk { + every { id } returns "default" + } + val otherSearchEngine: SearchEngine = mockk { + every { id } returns "other" + } + val components: Components = mockk { + every { core.store.state.search } returns mockk(relaxed = true) { + every { searchEngines } returns listOf(otherSearchEngine, defaultSearchEngine) + } + } + mockkStatic( + "org.mozilla.fenix.ext.FragmentKt", + "mozilla.components.browser.state.state.SearchStateKt", + ) { + every { any<Fragment>().requireComponents } returns components + every { any<SearchState>().selectedOrDefaultSearchEngine } returns defaultSearchEngine + + fragment.maybeSelectShortcutEngine(defaultSearchEngine.id) + + verify { fragment.interactor wasNot Called } + } + } + + @Test + fun `GIVEN the default search engine is not currently selected WHEN checking the need to update the current search engine THEN update it to the current engine`() { + fragment.interactor = mockk { + every { onSearchShortcutEngineSelected(any()) } just Runs + } + val defaultSearchEngine: SearchEngine = mockk { + every { id } returns "default" + } + val otherSearchEngine: SearchEngine = mockk { + every { id } returns "other" + } + val components: Components = mockk { + every { core.store.state.search } returns mockk(relaxed = true) { + every { searchEngines } returns listOf(otherSearchEngine, defaultSearchEngine) + } + } + mockkStatic( + "org.mozilla.fenix.ext.FragmentKt", + "mozilla.components.browser.state.state.SearchStateKt", + ) { + every { any<Fragment>().requireComponents } returns components + every { any<SearchState>().selectedOrDefaultSearchEngine } returns defaultSearchEngine + + fragment.maybeSelectShortcutEngine(otherSearchEngine.id) + + verify { fragment.interactor.onSearchShortcutEngineSelected(otherSearchEngine) } + } + } + + @Test + fun `GIVEN the currently selected search engine is unknown WHEN checking the need to update the current search engine THEN don't do anything`() { + fragment.interactor = mockk() + + fragment.maybeSelectShortcutEngine(null) + + verify { fragment.interactor wasNot Called } + } + + @Test + fun `GIVEN app is in private mode WHEN search dialog is created THEN the dialog is secure`() { + val activity: HomeActivity = mockk(relaxed = true) + val fragment = spyk(SearchDialogFragment()) + val layoutParams = LayoutParams() + layoutParams.flags = LayoutParams.FLAG_SECURE + + every { activity.browsingModeManager.mode.isPrivate } returns true + every { activity.window } returns mockk(relaxed = true) { + every { attributes } returns LayoutParams().apply { flags = LayoutParams.FLAG_SECURE } + } + every { fragment.requireActivity() } returns activity + every { fragment.requireContext() } returns testContext + + val dialog = fragment.onCreateDialog(null) + + assertEquals(LayoutParams.FLAG_SECURE, dialog.window?.attributes?.flags!! and LayoutParams.FLAG_SECURE) + } + + @Test + fun `GIVEN app is in normal mode WHEN search dialog is created THEN the dialog is not secure`() { + val activity: HomeActivity = mockk(relaxed = true) + val fragment = spyk(SearchDialogFragment()) + val layoutParams = LayoutParams() + layoutParams.flags = LayoutParams.FLAG_SECURE + + every { activity.browsingModeManager.mode.isPrivate } returns false + every { activity.window } returns mockk(relaxed = true) { + every { attributes } returns LayoutParams().apply { flags = LayoutParams.FLAG_SECURE } + } + every { fragment.requireActivity() } returns activity + every { fragment.requireContext() } returns testContext + + val dialog = fragment.onCreateDialog(null) + + assertEquals(0, dialog.window?.attributes?.flags!! and LayoutParams.FLAG_SECURE) + } +} + +private val fragmentName = SearchDialogFragment::class.java.canonicalName?.substringAfterLast('.')!! + +private fun getDestination(destinationName: String): NavBackStackEntry { + return mockk { + every { destination } returns mockk { + every { displayName } returns "test.id/$destinationName" + } + } +}
View it on GitLab: https://gitlab.torproject.org/tpo/applications/fenix/-/compare/cf3ce1ddef47a...