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

Commit 8ba132f1 authored by Xiaomiao Zhang's avatar Xiaomiao Zhang Committed by Android (Google) Code Review
Browse files

Merge "Invoke pin verification upon switching safe sites options" into main

parents 3b1a03f8 90050a13
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() {