Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 90050a13 authored by Xiaomiao Zhang's avatar Xiaomiao Zhang
Browse files

Invoke pin verification upon switching safe sites options

Test: atest SupervisionWebContentFiltersScreenTest
Test: atest SupervisionSafeSitesPreferenceTest
Test: deployed locally to a physical device
Flag: android.app.supervision.flags.enable_web_content_filters_screen
Bug: 408490556
Change-Id: I265a8fb4243e784130637f9d70db916469f5df97
parent e238e8d6
Loading
Loading
Loading
Loading
+51 −9
Original line number Diff line number Diff line
@@ -15,11 +15,15 @@
 */
package com.android.settings.supervision

import android.app.Activity
import android.content.Context
import android.content.Intent
import androidx.preference.Preference
import com.android.settings.R
import com.android.settingslib.datastore.Permissions
import com.android.settingslib.metadata.BooleanValuePreference
import com.android.settingslib.metadata.PreferenceLifecycleContext
import com.android.settingslib.metadata.PreferenceLifecycleProvider
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.metadata.ReadWritePermit
import com.android.settingslib.metadata.SensitivityLevel
@@ -30,7 +34,15 @@ import com.android.settingslib.widget.SelectorWithWidgetPreference
/** Base class of web content filters Safe sites preferences. */
sealed class SupervisionSafeSitesPreference(
    protected val dataStore: SupervisionSafeSitesDataStore
) : BooleanValuePreference, SelectorWithWidgetPreference.OnClickListener, PreferenceBinding {
) :
    BooleanValuePreference,
    SelectorWithWidgetPreference.OnClickListener,
    PreferenceBinding,
    PreferenceLifecycleProvider {
    private lateinit var lifeCycleContext: PreferenceLifecycleContext

    abstract val supervisionCredentialRequestCode: Int

    override fun storage(context: Context) = dataStore

    override fun getReadPermissions(context: Context) = Permissions.EMPTY
@@ -52,12 +64,18 @@ sealed class SupervisionSafeSitesPreference(

    override fun createWidget(context: Context) = SelectorWithWidgetPreference(context)

    override fun onRadioButtonClicked(emiter: SelectorWithWidgetPreference) {
        emiter.parent?.forEachRecursively {
            if (it is SelectorWithWidgetPreference) {
                it.isChecked = it == emiter
            }
    override fun onCreate(context: PreferenceLifecycleContext) {
        lifeCycleContext = context
    }

    override fun onRadioButtonClicked(emitter: SelectorWithWidgetPreference) {
        val intent = Intent(lifeCycleContext, ConfirmSupervisionCredentialsActivity::class.java)

        lifeCycleContext.startActivityForResult(
            intent,
            supervisionCredentialRequestCode,
            /* options= */ null,
        )
    }

    override fun bind(preference: Preference, metadata: PreferenceMetadata) {
@@ -67,12 +85,31 @@ sealed class SupervisionSafeSitesPreference(
            it.setOnClickListener(this)
        }
    }

    override fun onActivityResult(
        context: PreferenceLifecycleContext,
        requestCode: Int,
        resultCode: Int,
        data: Intent?,
    ): Boolean {
        if (requestCode != supervisionCredentialRequestCode) return false
        if (resultCode == Activity.RESULT_OK) {
            val preference = context.findPreference<SelectorWithWidgetPreference>(key)
            // Iterate through the SafeSites options and update the checked status.
            preference?.parent?.forEachRecursively {
                if (it is SelectorWithWidgetPreference) {
                    it.isChecked = it.key == key
                }
            }
            return true
        }
        return false
    }
}

/** The "Try to block explicit sites" preference. */
class SupervisionBlockExplicitSitesPreference(dataStore: SupervisionSafeSitesDataStore) :
    SupervisionSafeSitesPreference(dataStore) {

    override val key
        get() = KEY

@@ -82,22 +119,27 @@ class SupervisionBlockExplicitSitesPreference(dataStore: SupervisionSafeSitesDat
    override val summary
        get() = R.string.supervision_web_content_filters_browser_block_explicit_sites_summary

    override val supervisionCredentialRequestCode = REQUEST_CODE_SUPERVISION_CREDENTIALS

    companion object {
        const val KEY = "web_content_filters_browser_block_explicit_sites"
        const val REQUEST_CODE_SUPERVISION_CREDENTIALS = 10
    }
}

/** The "Allow all sites" preference. */
class SupervisionAllowAllSitesPreference(dataStore: SupervisionSafeSitesDataStore) :
    SupervisionSafeSitesPreference(dataStore) {

    override val key
        get() = KEY

    override val title
        get() = R.string.supervision_web_content_filters_browser_allow_all_sites_title

    override val supervisionCredentialRequestCode = REQUEST_CODE_SUPERVISION_CREDENTIALS

    companion object {
        const val KEY = "web_content_filters_browser_allow_all_sites"
        const val REQUEST_CODE_SUPERVISION_CREDENTIALS = 11
    }
}
+103 −13
Original line number Diff line number Diff line
@@ -15,13 +15,17 @@
 */
package com.android.settings.supervision

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.provider.Settings
import android.provider.Settings.Secure.BROWSER_CONTENT_FILTERS_ENABLED
import android.provider.Settings.SettingNotFoundException
import androidx.preference.Preference
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.R
import com.android.settingslib.metadata.PreferenceLifecycleContext
import com.android.settingslib.preference.createAndBindWidget
import com.android.settingslib.widget.SelectorWithWidgetPreference
import com.google.common.truth.Truth.assertThat
@@ -29,9 +33,16 @@ import org.junit.Assert.assertThrows
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.mock
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.eq
import org.mockito.kotlin.stub
import org.mockito.kotlin.verify

@RunWith(AndroidJUnit4::class)
class SupervisionSafeSitesPreferenceTest {
    private val mockLifeCycleContext = mock(PreferenceLifecycleContext::class.java)
    private val context: Context = ApplicationProvider.getApplicationContext()
    private lateinit var dataStore: SupervisionSafeSitesDataStore
    private lateinit var allowAllSitesPreference: SupervisionAllowAllSitesPreference
@@ -41,7 +52,9 @@ class SupervisionSafeSitesPreferenceTest {
    fun setUp() {
        dataStore = SupervisionSafeSitesDataStore(context)
        allowAllSitesPreference = SupervisionAllowAllSitesPreference(dataStore)
        allowAllSitesPreference.onCreate(mockLifeCycleContext)
        blockExplicitSitesPreference = SupervisionBlockExplicitSitesPreference(dataStore)
        blockExplicitSitesPreference.onCreate(mockLifeCycleContext)
    }

    @Test
@@ -80,6 +93,29 @@ class SupervisionSafeSitesPreferenceTest {
        assertThat(getBlockExplicitSitesWidget().isChecked).isTrue()
    }

    @Test
    fun clickBlockExplicitSites_credentialFailed() {
        Settings.Secure.putInt(context.getContentResolver(), BROWSER_CONTENT_FILTERS_ENABLED, 0)
        val blockExplicitSitesWidget = getBlockExplicitSitesWidget()
        assertThat(blockExplicitSitesWidget.isChecked).isFalse()

        blockExplicitSitesWidget.performClick()

        verifyConfirmSupervisionCredentialsActivityStarted(
            SupervisionBlockExplicitSitesPreference.REQUEST_CODE_SUPERVISION_CREDENTIALS
        )

        val result =
            blockExplicitSitesPreference.onActivityResult(
                mockLifeCycleContext,
                SupervisionBlockExplicitSitesPreference.REQUEST_CODE_SUPERVISION_CREDENTIALS,
                Activity.RESULT_CANCELED,
                null,
            )

        assertThat(result).isFalse()
    }

    @Test
    fun clickBlockExplicitSites_enablesFilter() {
        Settings.Secure.putInt(context.getContentResolver(), BROWSER_CONTENT_FILTERS_ENABLED, 0)
@@ -88,6 +124,20 @@ class SupervisionSafeSitesPreferenceTest {

        blockExplicitSitesWidget.performClick()

        verifyConfirmSupervisionCredentialsActivityStarted(
            SupervisionBlockExplicitSitesPreference.REQUEST_CODE_SUPERVISION_CREDENTIALS
        )

        val result =
            blockExplicitSitesPreference.onActivityResult(
                mockLifeCycleContext,
                SupervisionBlockExplicitSitesPreference.REQUEST_CODE_SUPERVISION_CREDENTIALS,
                Activity.RESULT_OK,
                null,
            )

        assertThat(result).isTrue()
        assertThat(blockExplicitSitesWidget.isChecked).isTrue()
        assertThat(
                Settings.Secure.getInt(
                    context.getContentResolver(),
@@ -95,7 +145,6 @@ class SupervisionSafeSitesPreferenceTest {
                )
            )
            .isEqualTo(1)
        assertThat(blockExplicitSitesWidget.isChecked).isTrue()
    }

    @Test
@@ -103,9 +152,22 @@ class SupervisionSafeSitesPreferenceTest {
        Settings.Secure.putInt(context.getContentResolver(), BROWSER_CONTENT_FILTERS_ENABLED, 1)
        val allowAllSitesWidget = getAllowAllSitesWidget()
        assertThat(allowAllSitesWidget.isChecked).isFalse()

        allowAllSitesWidget.performClick()

        verifyConfirmSupervisionCredentialsActivityStarted(
            SupervisionAllowAllSitesPreference.REQUEST_CODE_SUPERVISION_CREDENTIALS
        )

        val result =
            allowAllSitesPreference.onActivityResult(
                mockLifeCycleContext,
                SupervisionAllowAllSitesPreference.REQUEST_CODE_SUPERVISION_CREDENTIALS,
                Activity.RESULT_OK,
                null,
            )

        assertThat(result).isTrue()
        assertThat(allowAllSitesWidget.isChecked).isTrue()
        assertThat(
                Settings.Secure.getInt(
                    context.getContentResolver(),
@@ -113,14 +175,42 @@ class SupervisionSafeSitesPreferenceTest {
                )
            )
            .isEqualTo(0)
        assertThat(allowAllSitesWidget.isChecked).isTrue()
    }

    private fun getBlockExplicitSitesWidget(): SelectorWithWidgetPreference {
        return blockExplicitSitesPreference.createAndBindWidget(context)
        val widget: SelectorWithWidgetPreference =
            blockExplicitSitesPreference.createAndBindWidget(context)
        mockLifeCycleContext.stub {
            on { findPreference<Preference>(SupervisionBlockExplicitSitesPreference.KEY) } doReturn
                widget
            on {
                requirePreference<Preference>(SupervisionBlockExplicitSitesPreference.KEY)
            } doReturn widget
        }
        return widget
    }

    private fun getAllowAllSitesWidget(): SelectorWithWidgetPreference {
        return allowAllSitesPreference.createAndBindWidget(context)
        val widget: SelectorWithWidgetPreference =
            allowAllSitesPreference.createAndBindWidget(context)
        mockLifeCycleContext.stub {
            on { findPreference<Preference>(SupervisionAllowAllSitesPreference.KEY) } doReturn
                widget
            on { requirePreference<Preference>(SupervisionAllowAllSitesPreference.KEY) } doReturn
                widget
        }
        return widget
    }

    private fun verifyConfirmSupervisionCredentialsActivityStarted(requestCode: Int) {
        val intentCaptor = argumentCaptor<Intent>()

        verify(mockLifeCycleContext)
            .startActivityForResult(intentCaptor.capture(), eq(requestCode), eq(null))

        assertThat(intentCaptor.allValues.size).isEqualTo(1)

        assertThat(intentCaptor.firstValue.component?.className)
            .isEqualTo(ConfirmSupervisionCredentialsActivity::class.java.name)
    }
}
+43 −2
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
package com.android.settings.supervision

import android.app.Activity
import android.app.supervision.flags.Flags
import android.content.Context
import android.platform.test.annotations.DisableFlags
@@ -68,7 +69,7 @@ class SupervisionWebContentFiltersScreenTest {

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_WEB_CONTENT_FILTERS_SCREEN)
    fun switchSafeSitesPreferences() {
    fun switchSafeSitesPreferences_succeedWithParentPin() {
        FragmentScenario.launchInContainer(supervisionWebContentFiltersScreen.fragmentClass())
            .onFragment { fragment ->
                val allowAllSitesPreference =
@@ -79,17 +80,57 @@ class SupervisionWebContentFiltersScreenTest {
                    fragment.findPreference<SelectorWithWidgetPreference>(
                        SupervisionBlockExplicitSitesPreference.KEY
                    )!!

                assertThat(allowAllSitesPreference.isChecked).isTrue()
                assertThat(blockExplicitSitesPreference.isChecked).isFalse()

                blockExplicitSitesPreference.performClick()

                // Pretend the PIN verification succeeded.
                fragment.onActivityResult(
                    requestCode =
                        SupervisionBlockExplicitSitesPreference
                            .REQUEST_CODE_SUPERVISION_CREDENTIALS,
                    resultCode = Activity.RESULT_OK,
                    data = null,
                )

                assertThat(blockExplicitSitesPreference.isChecked).isTrue()
                assertThat(allowAllSitesPreference.isChecked).isFalse()
            }
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_WEB_CONTENT_FILTERS_SCREEN)
    fun switchSafeSitesPreferences_failWithoutParentPin() {
        FragmentScenario.launchInContainer(supervisionWebContentFiltersScreen.fragmentClass())
            .onFragment { fragment ->
                val allowAllSitesPreference =
                    fragment.findPreference<SelectorWithWidgetPreference>(
                        SupervisionAllowAllSitesPreference.KEY
                    )!!
                val blockExplicitSitesPreference =
                    fragment.findPreference<SelectorWithWidgetPreference>(
                        SupervisionBlockExplicitSitesPreference.KEY
                    )!!

                assertThat(allowAllSitesPreference.isChecked).isTrue()
                assertThat(blockExplicitSitesPreference.isChecked).isFalse()

                blockExplicitSitesPreference.performClick()

                // Pretend the PIN verification succeeded.
                fragment.onActivityResult(
                    requestCode =
                        SupervisionAllowAllSitesPreference.REQUEST_CODE_SUPERVISION_CREDENTIALS,
                    resultCode = Activity.RESULT_CANCELED,
                    data = null,
                )

                assertThat(blockExplicitSitesPreference.isChecked).isFalse()
                assertThat(allowAllSitesPreference.isChecked).isTrue()
            }
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_WEB_CONTENT_FILTERS_SCREEN)
    fun switchSafeSearchPreferences() {