diff --git a/res/values/strings.xml b/res/values/strings.xml index e8d3618f071..1e8ba4e4f1a 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -14309,6 +14309,14 @@ Data usage charges may apply. Forgot PIN Web content filters + + Google Chrome and Web + + Try to block explicit sites + + No filter is perfect, but this should help hide sexually explicit sites + + Allow all sites %1$s animation diff --git a/src/com/android/settings/supervision/SupervisionSafeSitesPreference.kt b/src/com/android/settings/supervision/SupervisionSafeSitesPreference.kt new file mode 100644 index 00000000000..aaa5a333a86 --- /dev/null +++ b/src/com/android/settings/supervision/SupervisionSafeSitesPreference.kt @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.settings.supervision + +import android.content.Context +import androidx.preference.Preference +import com.android.settings.R +import com.android.settingslib.datastore.KeyValueStore +import com.android.settingslib.datastore.Permissions +import com.android.settingslib.datastore.SettingsSecureStore +import com.android.settingslib.metadata.BooleanValuePreference +import com.android.settingslib.metadata.PreferenceMetadata +import com.android.settingslib.metadata.ReadWritePermit +import com.android.settingslib.metadata.SensitivityLevel +import com.android.settingslib.preference.PreferenceBinding +import com.android.settingslib.preference.forEachRecursively +import com.android.settingslib.widget.SelectorWithWidgetPreference + +/** Base class of web content filters Safe sites preferences. */ +sealed class SupervisionSafeSitesPreference : + BooleanValuePreference, SelectorWithWidgetPreference.OnClickListener, PreferenceBinding { + override fun storage(context: Context): KeyValueStore = SettingsSecureStore.get(context) + + override fun getReadPermissions(context: Context) = Permissions.EMPTY + + override fun getWritePermissions(context: Context) = Permissions.EMPTY + + override fun getReadPermit(context: Context, callingPid: Int, callingUid: Int) = + ReadWritePermit.ALLOW + + override fun getWritePermit( + context: Context, + value: Boolean?, + callingPid: Int, + callingUid: Int, + ) = ReadWritePermit.DISALLOW + + override val sensitivityLevel + get() = SensitivityLevel.NO_SENSITIVITY + + 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 bind(preference: Preference, metadata: PreferenceMetadata) { + super.bind(preference, metadata) + (preference as SelectorWithWidgetPreference).also { + // TODO(b/401568468): Set the isChecked value using stored values. + it.isChecked = (it.key == SupervisionAllowAllSitesPreference.KEY) + it.setOnClickListener(this) + } + } +} + +/** The "Try to block explicit sites" preference. */ +class SupervisionBlockExplicitSitesPreference : SupervisionSafeSitesPreference() { + + override val key + get() = KEY + + override val title + get() = R.string.supervision_web_content_filters_browser_block_explicit_sites_title + + override val summary + get() = R.string.supervision_web_content_filters_browser_block_explicit_sites_summary + + companion object { + const val KEY = "web_content_filters_browser_block_explicit_sites" + } +} + +/** The "Allow all sites" preference. */ +class SupervisionAllowAllSitesPreference : SupervisionSafeSitesPreference() { + + override val key + get() = KEY + + override val title + get() = R.string.supervision_web_content_filters_browser_allow_all_sites_title + + companion object { + const val KEY = "web_content_filters_browser_allow_all_sites" + } +} diff --git a/src/com/android/settings/supervision/SupervisionWebContentFiltersScreen.kt b/src/com/android/settings/supervision/SupervisionWebContentFiltersScreen.kt index ef46b2084da..0a2891b5c5e 100644 --- a/src/com/android/settings/supervision/SupervisionWebContentFiltersScreen.kt +++ b/src/com/android/settings/supervision/SupervisionWebContentFiltersScreen.kt @@ -18,6 +18,7 @@ package com.android.settings.supervision import android.app.supervision.flags.Flags import android.content.Context import com.android.settings.R +import com.android.settingslib.metadata.PreferenceCategory import com.android.settingslib.metadata.ProvidePreferenceScreen import com.android.settingslib.metadata.preferenceHierarchy import com.android.settingslib.preference.PreferenceScreenCreator @@ -41,10 +42,19 @@ class SupervisionWebContentFiltersScreen : PreferenceScreenCreator { override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(context, this) { - // TODO(b/395134536) implement the screen. + +PreferenceCategory( + BROWSER_RADIO_BUTTON_GROUP, + R.string.supervision_web_content_filters_browser_title, + ) += + { + +SupervisionBlockExplicitSitesPreference() + +SupervisionAllowAllSitesPreference() + } + // TODO(b/401569571) implement the SafeSearch group. } companion object { const val KEY = "supervision_web_content_filters" + internal const val BROWSER_RADIO_BUTTON_GROUP = "browser_radio_button_group" } } diff --git a/tests/robotests/src/com/android/settings/supervision/SupervisionSafeSitesPreferenceTest.kt b/tests/robotests/src/com/android/settings/supervision/SupervisionSafeSitesPreferenceTest.kt new file mode 100644 index 00000000000..5be7a1167e4 --- /dev/null +++ b/tests/robotests/src/com/android/settings/supervision/SupervisionSafeSitesPreferenceTest.kt @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.settings.supervision + +import android.content.Context +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settings.R +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class SupervisionSafeSitesPreferenceTest { + private val context: Context = ApplicationProvider.getApplicationContext() + + private val allowAllSitesPreference = SupervisionAllowAllSitesPreference() + + private val blockExplicitSitesPreference = SupervisionBlockExplicitSitesPreference() + + @Test + fun getTitle_allowAllSites() { + assertThat(allowAllSitesPreference.title) + .isEqualTo(R.string.supervision_web_content_filters_browser_allow_all_sites_title) + } + + @Test + fun getTitle_blockExplicitSites() { + assertThat(blockExplicitSitesPreference.title) + .isEqualTo(R.string.supervision_web_content_filters_browser_block_explicit_sites_title) + } + + @Test + fun getSummary_blockExplicitSites() { + assertThat(blockExplicitSitesPreference.summary) + .isEqualTo( + R.string.supervision_web_content_filters_browser_block_explicit_sites_summary + ) + } +}