Commit 216f33a3 authored by Alexandru2909's avatar Alexandru2909 Committed by Richard Pospesel
Browse files

Add FLAG_SECURE to SearchDialogFragment

parent 36285ece
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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())
            }
        }
    }

+212 −0
Original line number Diff line number Diff line
/* 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"
        }
    }
}